diff --git a/TensorFlow/built-in/audio/Tacotron2-v1-Encoder_ID1997_for_TensorFlow/test/train_RT2_performance_1p.sh b/TensorFlow/built-in/audio/Tacotron2-v1-Encoder_ID1997_for_TensorFlow/test/train_RT2_performance_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..88fcb9ff1b0fa008374671e7884f0292fd2bddb0 --- /dev/null +++ b/TensorFlow/built-in/audio/Tacotron2-v1-Encoder_ID1997_for_TensorFlow/test/train_RT2_performance_1p.sh @@ -0,0 +1,209 @@ +#!/bin/bash +#当前路径,不需要修改 +cur_path=`pwd` + +#集合通信参数,不需要修改 + +export RANK_SIZE=1 +export JOB_ID=10087 + +RANK_ID_START=0 + +#使能RT2.0 +export ENABLE_RUNTIME_V2=1 + +# 数据集路径,保持为空,不需要修改 +data_path="" + + +#基础参数,需要模型审视修改 +#网络名称,同目录名称 +Network="Tacotron2-v1-Encoder_ID1997_for_TensorFlow" +#训练epoch +train_epochs=2 +#训练step +train_steps=50 +#训练batch_size +batch_size=16 +#学习率 +learning_rate=1e-3 + + +#维测参数,precision_mode需要模型审视修改 +precision_mode="allow_mix_precision" +#维持参数,以下不需要修改 +over_dump=False +data_dump_flag=False +data_dump_step="10" +profiling=False +autotune=False + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo "usage:./train_performance_1p.sh " + echo " " + echo "parameter explain: + --precision_mode precision mode(allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision) + --over_dump if or not over detection, default is False + --data_dump_flag data dump flag, default is False + --data_dump_step data dump step, default is 10 + --profiling if or not profiling for performance debug, default is False + --data_path source data of training + --max_step # of step for training + --learning_rate learning rate + --batch batch size + --modeldir model dir + --save_interval save interval for ckpt + --loss_scale enable loss scale ,default is False + --dynamic_bs dynamic batch size, default is False + -h/--help show help message + " + exit 1 +fi + +#参数校验,不需要修改 +for para in $* +do + if [[ $para == --precision_mode* ]];then + precision_mode=`echo ${para#*=}` + elif [[ $para == --over_dump* ]];then + over_dump=`echo ${para#*=}` + over_dump_path=${cur_path}/output/overflow_dump + mkdir -p ${over_dump_path} + elif [[ $para == --data_dump_flag* ]];then + data_dump_flag=`echo ${para#*=}` + data_dump_path=${cur_path}/output/data_dump + mkdir -p ${data_dump_path} + elif [[ $para == --data_dump_step* ]];then + data_dump_step=`echo ${para#*=}` + elif [[ $para == --profiling* ]];then + profiling=`echo ${para#*=}` + profiling_dump_path=${cur_path}/output/profiling + mkdir -p ${profiling_dump_path} + elif [[ $para == --autotune* ]];then + autotune=`echo ${para#*=}` + mv $install_path/fwkacllib/data/rl/Ascend910/custom $install_path/fwkacllib/data/rl/Ascend910/custom_bak + mv $install_path/fwkacllib/data/tiling/Ascend910/custom $install_path/fwkacllib/data/tiling/Ascend910/custom_bak + autotune_dump_path=${cur_path}/output/autotune_dump + mkdir -p ${autotune_dump_path}/GA + mkdir -p ${autotune_dump_path}/rl + cp -rf $install_path/fwkacllib/data/tiling/Ascend910/custom ${autotune_dump_path}/GA/ + cp -rf $install_path/fwkacllib/data/rl/Ascend910/custom ${autotune_dump_path}/RL/ + elif [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + elif [[ $para == --max_step* ]];then + train_steps=`echo ${para#*=}` + elif [[ $para == --learning_rate* ]];then + learning_rate=`echo ${para#*=}` + elif [[ $para == --batch* ]];then + batch_size=`echo ${para#*=}` + elif [[ $para == --modeldir* ]];then + modeldir=`echo ${para#*=}` + elif [[ $para == --save_interval* ]];then + save_interval=`echo ${para#*=}` + elif [[ $para == --loss_scale* ]];then + loss_scale=`echo ${para#*=}` + elif [[ $para == --dynamic_bs* ]];then + dynamic_bs=`echo ${para#*=}` + fi +done + +#校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be config" + exit 1 +fi + +#训练开始时间,不需要修改 +start_time=$(date +%s) +cd $cur_path/../ +#进入训练脚本目录,需要模型审视修改 +for((RANK_ID=$RANK_ID_START;RANK_ID<$((RANK_SIZE+RANK_ID_START));RANK_ID++)); +do + #设置环境变量,不需要修改 + echo "Device ID: $ASCEND_DEVICE_ID" + export RANK_ID=$RANK_ID + + #创建DeviceID输出目录,不需要修改 + if [ -d ${cur_path}/output/${ASCEND_DEVICE_ID} ];then + rm -rf ${cur_path}/output/${ASCEND_DEVICE_ID} + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + else + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + fi + + #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 + #--data_path, --model_dir, --precision_mode, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path,--autotune + nohup python3 train_rt.py \ + --log_dir=${cur_path}/output \ + --log_name="test" \ + --data_paths=${data_path} \ + --epoch=${train_epochs} \ + --num_iterations=${train_steps} \ + --batch_size=${batch_size} \ + --dynamic_bs=${dynamic_bs} \ + --precision_mode=${precision_mode} \ + --over_dump=${over_dump} \ + --over_dump_path=${over_dump_path} \ + --data_dump_flag=${data_dump_flag} \ + --data_dump_step=${data_dump_step} \ + --data_dump_path=${data_dump_path} \ + --profiling=${profiling} \ + --profiling_dump_path=${profiling_dump_path} \ + --deltree=True > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & +if [ $? -ne 0 ];then + exit 1 +fi +done +wait + +#训练结束时间,不需要修改 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +#结果打印,不需要修改 +echo "------------------ Final result ------------------" +#输出性能FPS,需要模型审视修改 +t_step_time=`grep "perf = " $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log | sed '1d' | awk -F "=" '{print $3}' | awk '{sum+=$1} END {print sum}'` +FPS=`awk 'BEGIN {printf "%.2f\n", '${batch_size}'*('${train_steps}'-'1')/'${t_step_time}'}'` + +TrainingTime=`awk 'BEGIN {printf "%.2f\n", '1000'*'${batch_size}'/'${FPS}'}'` +#打印,不需要修改 +echo "Final Performance images/sec : $FPS" + +#输出训练精度,需要模型审视修改 +#train_accuracy=`grep "Accuracy:" $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log | awk -F " " '{print $2}'` +#打印,不需要修改 +#echo "Final Train Accuracy : ${train_accuracy}" +echo "E2E Training Duration sec : $e2e_time" + +#性能看护结果汇总 +#训练用例信息,不需要修改 +BatchSize=${batch_size} +DeviceType=`uname -m` +if [[ $dynamic_bs == "" || $dynamic_bs == "False" ]];then + CaseName=${Network}_bs${BatchSize}_${RANK_SIZE}'p'_'RT2'_'perf' +else + CaseName=${Network}_dynamic_bs${BatchSize}_${RANK_SIZE}'p'_'RT2'_'perf' +fi + +##获取性能数据,不需要修改 +#吞吐量 +ActualFPS=${FPS} + +#从train_$ASCEND_DEVICE_ID.log提取Loss到train_${CaseName}_loss.txt中,需要根据模型审视 +grep 'Loss =' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk '{print $6}' > $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt + +#最后一个迭代loss值,不需要修改 +ActualLoss=`awk 'END {print}' $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt` + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${BatchSize}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = ${DeviceType}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${ActualFPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${TrainingTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log diff --git a/TensorFlow/built-in/audio/Tacotron2-v1-Encoder_ID1997_for_TensorFlow/train_rt.py b/TensorFlow/built-in/audio/Tacotron2-v1-Encoder_ID1997_for_TensorFlow/train_rt.py new file mode 100644 index 0000000000000000000000000000000000000000..748c4ac102d2c07c7546a79317c4d5fb163ae69f --- /dev/null +++ b/TensorFlow/built-in/audio/Tacotron2-v1-Encoder_ID1997_for_TensorFlow/train_rt.py @@ -0,0 +1,377 @@ +# +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================== + +from __future__ import print_function +from npu_bridge.npu_init import * +from tqdm import tqdm +import argparse +import os +import time +from data_load import make_dataset, get_batch, load_vocab +from hyperparams import Hyperparams as hp +from networks import encoder, decoder, converter +import tensorflow as tf +from fn_utils import infolog +import synthesize +from utils import * +from tensorflow.core.protobuf.rewriter_config_pb2 import RewriterConfig + +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' + +class Graph(): + + def __init__(self, input_data, config=None, training=True, train_form='Both'): + (self.char2idx, self.idx2char) = load_vocab() + # self.graph = tf.Graph() + # with self.graph.as_default(): + if training: + # (self.origx, self.x, self.y1, self.y2, self.y3, self.num_batch) = get_batch(config, train_form) + # text_tests + self.origx = input_data["origx"] + # texts + self.x = input_data["x"] + # mels + self.y1 = input_data["y1"] + # dones + self.y2 = None + if "y2" in input_data.keys(): + self.y2 = input_data["y2"] + # mags + self.y3 = None + if "y3" in input_data.keys(): + self.y3 = input_data["y3"] + print("========After get_batch") + else: + self.x = tf.placeholder(tf.int32, shape=(config.batch_size, hp.T_x)) + self.y1 = tf.placeholder(tf.float32, shape=(config.batch_size, (hp.T_y // hp.r), (hp.n_mels * hp.r))) + if (train_form != 'Converter'): + with tf.variable_scope('encoder'): + self.encoded = encoder(self.x, training=training) + with tf.variable_scope('decoder'): + (self.mel_output, self.bef_mel_output, self.done_output, self.decoder_state, self.LTSM, self.step) = \ + decoder(self.y1, self.encoded, config.batch_size, training=training) + self.cell_state = self.decoder_state.cell_state + self.mel_output = tf.nn.sigmoid(self.mel_output) + if (train_form == 'Both'): + with tf.variable_scope('converter'): + self.converter_input = self.mel_output + self.mag_logits = converter(self.converter_input, training=training) + self.mag_output = tf.nn.sigmoid(self.mag_logits) + elif (train_form == 'Converter'): + with tf.variable_scope('converter'): + self.converter_input = self.y1 + self.mag_logits = converter(self.converter_input, training=training) + self.mag_output = tf.nn.sigmoid(self.mag_logits) + print("========After mag_logits converter") + self.global_step = tf.Variable(0, name='global_step', trainable=False) + if training: + if (train_form != 'Converter'): + self.loss1 = tf.reduce_mean(tf.abs((self.mel_output - self.y1))) + self.loss1b = tf.reduce_mean(tf.abs((self.bef_mel_output - self.y1))) + if hp.include_dones: + self.loss2 = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=self.done_output, + labels=self.y2)) + if (train_form != 'Encoder'): + self.loss3 = tf.reduce_mean(tf.abs((self.mag_output - self.y3))) + print("========After self.loss3") + if (train_form == 'Both'): + if hp.include_dones: + self.loss = (((self.loss1 + self.loss1b) + self.loss2) + self.loss3) + else: + self.loss = ((self.loss1 + self.loss1b) + self.loss3) + elif (train_form == 'Encoder'): + if hp.include_dones: + self.loss = ((self.loss1 + self.loss1b) + self.loss2) + else: + self.loss = (self.loss1 + self.loss1b) + else: + self.loss = self.loss3 + print("========After self.loss") + + #self.optimizer = tf.train.AdamOptimizer(learning_rate=hp.lr) + #self.optimizer = NPUDistributedOptimizer(self.optimizer) + opt_tmp = tf.train.AdamOptimizer(learning_rate=hp.lr) + # loss_scale_manager = ExponentialUpdateLossScaleManager(init_loss_scale=2*32, + # incr_every_n_steps=1000, + # decr_every_n_nan_or_inf=2, + # decr_ratio=0.5) + # overflow also update for dynamic_bs + loss_scale_manager = FixedLossScaleManager(loss_scale=1024, enable_overflow_check=False) + self.optimizer = NPULossScaleOptimizer(opt_tmp, loss_scale_manager) + + self.gvs = self.optimizer.compute_gradients(self.loss) + self.clipped = [] + print("========After self.gvs") + for (grad, var) in self.gvs: + grad = (grad if (grad is None) else tf.clip_by_value(grad, ((- 1.0) * hp.max_grad_val), hp.max_grad_val)) + grad = (grad if (grad is None) else tf.clip_by_norm(grad, hp.max_grad_norm)) + self.clipped.append((grad, var)) + self.train_op = self.optimizer.apply_gradients(self.clipped, global_step=self.global_step) + tf.summary.scalar('loss', self.loss) + print("========After tf.summary.scalar") + if (train_form != 'Converter'): + tf.summary.histogram('mel_output', self.mel_output) + tf.summary.histogram('mel_actual', self.y1) + tf.summary.scalar('loss1', self.loss1) + if hp.include_dones: + tf.summary.histogram('done_output', self.done_output) + tf.summary.histogram('done_actual', self.y2) + tf.summary.scalar('loss2', self.loss2) + if (train_form != 'Encoder'): + tf.summary.histogram('mag_output', self.mag_output) + tf.summary.histogram('mag_actual', self.y3) + tf.summary.scalar('loss3', self.loss3) + self.merged = tf.summary.merge_all() + print("========After self.merged") + +class GraphTest(): + + def __init__(self, config=None): + (self.char2idx, self.idx2char) = load_vocab() + self.graph = tf.Graph() + with self.graph.as_default(): + (self.origx, _, _, _, _, _) = get_batch(config, 'Encoder') + +def main(): + print() + parser = argparse.ArgumentParser() + parser.add_argument('--log_dir', default=hp.logdir) + parser.add_argument('--log_name', default=hp.logname) + parser.add_argument('--sample_dir', default=hp.sampledir) + parser.add_argument('--data_paths', default=hp.data) + parser.add_argument('--load_path', default=None) + parser.add_argument('--load_converter', default=None) + parser.add_argument('--deltree', default=False) + parser.add_argument('--summary_interval', type=int, default=hp.summary_interval) + parser.add_argument('--test_interval', type=int, default=hp.test_interval) + parser.add_argument('--checkpoint_interval', type=int, default=hp.checkpoint_interval) + parser.add_argument('--num_iterations', type=int, default=hp.num_iterations) + parser.add_argument('--epoch', type=int, default=2) + parser.add_argument('--batch_size', type=int, default=hp.batch_size) + + parser.add_argument('--data_dump_flag', type=str, default='False') + parser.add_argument('--over_dump', type=str, default='False') + parser.add_argument('--profiling', type=str, default='False') + parser.add_argument('--precision_mode', type=str, default='allow_fp32_to_fp16', + help='allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision.') + parser.add_argument('--data_dump_path', type=str, default='/home/data') + parser.add_argument('--data_dump_step', type=str, default='10') + parser.add_argument('--over_dump_path', type=str, default='/home/data') + parser.add_argument('--profiling_dump_path', type=str, default='/home/data') + parser.add_argument('--dynamic_bs', default=False) + + config = parser.parse_args() + config.log_dir = ((config.log_dir + '/') + config.log_name) + if (not os.path.exists(config.log_dir)): + os.makedirs(config.log_dir) + elif config.deltree: + for the_file in os.listdir(config.log_dir): + file_path = os.path.join(config.log_dir, the_file) + os.unlink(file_path) + log_path = os.path.join((config.log_dir + '/'), 'train.log') + infolog.init(log_path, 'log') + checkpoint_path = os.path.join(config.log_dir, 'model.ckpt') + + session_config = tf.ConfigProto() + custom_op = session_config.graph_options.rewrite_options.custom_optimizers.add() + custom_op.name = "NpuOptimizer" + custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes(config.precision_mode) + if config.dynamic_bs: + # custom_op.parameter_map["dynamic_input"].b = True + # custom_op.parameter_map["dynamic_graph_execute_mode"].s = tf.compat.as_bytes("dynamic_execute") + # custom_op.parameter_map["dynamic_inputs_shape_range"].s = tf.compat.as_bytes("data:[1~200,200],[1~200,810,80],[1~200,810,1025]") + # add for bs=128/160 + custom_op.parameter_map["graph_memory_max_size"].s = tf.compat.as_bytes(str(30 * 1024 * 1024 * 1024)) + custom_op.parameter_map["variable_memory_max_size"].s = tf.compat.as_bytes(str(1 * 1024 * 1024 * 1024)) + else: + custom_op.parameter_map["enable_data_pre_proc"].b = True + + if config.data_dump_flag == 'True': + custom_op.parameter_map["enable_dump"].b = True + custom_op.parameter_map["dump_path"].s = tf.compat.as_bytes(config.data_dump_path) + custom_op.parameter_map["dump_step"].s = tf.compat.as_bytes(config.data_dump_step) + custom_op.parameter_map["dump_mode"].s = tf.compat.as_bytes("all") + if config.over_dump == 'True': + custom_op.parameter_map["enable_dump_debug"].b = True + custom_op.parameter_map["dump_path"].s = tf.compat.as_bytes(config.over_dump_path) + custom_op.parameter_map["dump_debug_mode"].s = tf.compat.as_bytes("all") + if config.profiling == 'True': + custom_op.parameter_map["profiling_mode"].b = True + custom_op.parameter_map["profiling_options"].s = tf.compat.as_bytes('{"output":"' + config.profiling_dump_path + '", \ + "task_trace":"on", \ + "training_trace":"on", \ + "fp_point":"converter/converter/converter_rnn/add_1converter/converter/converter_rnn/mul_1", \ + "bp_point":"gradients/converter/converter/converter_conv/converter_conv_0/l2_normalize/Square_grad/Mulgradients/converter/converter/converter_conv/converter_conv_0/l2_normalize/Square_grad/Mul_1gradients/AddN_20"}') + + session_config.graph_options.rewrite_options.remapping = RewriterConfig.OFF + session_config.graph_options.rewrite_options.memory_optimization = RewriterConfig.OFF + npu_config = npu_config_proto(config_proto=session_config) + + train_dataset, num_batch = make_dataset(config, hp.train_form) + iterator = train_dataset.make_initializable_iterator() + + if (hp.train_form == 'Both'): + if hp.include_dones: + (texts, texts_tests, mels, mags, dones) = iterator.get_next() + input_data = {"origx": texts_tests, "x": texts, "y1": mels, "y2": dones, "y3": mags} + else: + (texts, texts_tests, mels, mags) = iterator.get_next() + input_data = {"origx": texts_tests, "x": texts, "y1": mels, "y3": mags} + elif (hp.train_form == 'Encoder'): + if hp.include_dones: + (texts, texts_tests, mels, dones) = iterator.get_next() + input_data = {"origx": texts_tests, "x": texts, "y1": mels, "y2": dones} + else: + (texts, texts_tests, mels) = iterator.get_next() + input_data = {"origx": texts_tests, "x": texts, "y1": mels} + else: + (texts, texts_tests, mels, mags) = iterator.get_next() + input_data = {"origx": texts_tests, "x": texts, "y1": mels, "y3": mags} + + if (hp.test_only == 0): + g = Graph(input_data=input_data, config=config, training=True, train_form=hp.train_form) + print('Training Graph loaded') + if (hp.test_graph or (hp.test_only > 0)): + g2 = Graph(config=config, training=False, train_form=hp.train_form) + print('Testing Graph loaded') + if (config.load_converter or (hp.test_only > 0)): + g_conv = Graph(config=config, training=False, train_form='Converter') + print('Converter Graph loaded') + print("========After graph") + + num_step = config.num_iterations if config.num_iterations < num_batch else num_batch + print("========After session config") + if (hp.test_only == 0): + with tf.Session(config=npu_config) as sess: + if config.load_path: + infolog.log(('Resuming from checkpoint: %s ' % tf.train.latest_checkpoint(config.log_dir)), slack=True) + tf.train.Saver().restore(sess, tf.train.latest_checkpoint(config.log_dir)) + else: + infolog.log('Starting new training', slack=True) + # summary_writer = tf.summary.FileWriter(config.log_dir, sess.graph) + # print("========After summary_writer") + sess.run(iterator.initializer) + sess.run(tf.global_variables_initializer()) + for epoch in range(1, config.epoch): + losses = [0, 0, 0, 0, 0] + for step in tqdm(range(num_step)): + startTime = time.time() + if (hp.train_form == 'Both'): + if hp.include_dones: + fetch = [g.global_step, g.merged, g.loss, g.loss1, g.loss1b, g.loss2, g.loss3, g.train_op] + (gs, merged, loss, loss1, loss1b, loss2, loss3, _) = sess.run(fetches=fetch) + loss_one = [loss, loss1, loss1b, loss2, loss3] + else: + fetch = [g.global_step, g.loss, g.loss1, g.loss1b, g.loss3, g.train_op] + (gs, loss, loss1, loss1b, loss3, _) = sess.run(fetches=fetch) + loss_one = [loss, loss1, loss1b, loss3, 0] + elif (hp.train_form == 'Encoder'): + if hp.include_dones: + fetch = [g.global_step, g.merged, g.loss, g.loss1, g.loss1b, g.loss2, g.train_op] + (gs, merged, loss, loss1, loss1b, loss2, _) = sess.run(fetches=fetch) + loss_one = [loss, loss1, loss1b, loss2, 0] + else: + fetch = [g.global_step, g.loss, g.loss1, g.loss1b, g.train_op] + (gs, loss, loss1, loss1b, _) = sess.run(fetches=fetch) + loss_one = [loss, loss1, loss1b, 0, 0] + else: + print("========before sess.run") + fetch = [g.global_step, g.merged, g.loss, g.train_op] + (gs, merged, loss, _) = sess.run(fetches=fetch) + loss_one = [loss, 0, 0, 0, 0] + print("========After sess.run") + endTime = time.time() + losses = [(x + y) for (x, y) in zip(losses, loss_one)] + infolog.log(('Epoch %d (%04d): Loss = %.8f perf = %.4f' % (epoch, gs, loss, endTime - startTime))) + # losses = [(x / g.num_batch) for x in losses] + losses = [(x / num_batch) for x in losses] + print('###############################################################################') + if (hp.train_form == 'Both'): + if hp.include_dones: + infolog.log(('Epoch %d (%04d): Loss = %.8f Loss1 = %.8f Loss1b = %.8f Loss2 = %.8f Loss3 = %.8f' % (epoch, gs, losses[0], losses[1], losses[2], losses[3], losses[4]))) + else: + infolog.log(('Epoch %d (%04d): Loss = %.8f Loss1 = %.8f Loss1b = %.8f Loss3 = %.8f' % (epoch, gs, losses[0], losses[1], losses[2], losses[3]))) + elif (hp.train_form == 'Encoder'): + if hp.include_dones: + infolog.log(('Epoch %d (%04d): Loss = %.8f Loss1 = %.8f Loss1b = %.8f Loss2 = %.8f' % (epoch, gs, losses[0], losses[1], losses[2], losses[3]))) + else: + infolog.log(('Epoch %d (%04d): Loss = %.8f Loss1 = %.8f Loss1b = %.8f' % (epoch, gs, losses[0], losses[1], losses[2]))) + else: + pass + print('###############################################################################') + print("========After for num_batch") + if not config.dynamic_bs and ((epoch % config.summary_interval) == 0): + infolog.log('Saving summary') + # summary_writer.add_summary(merged, gs) + if (hp.train_form == 'Both'): + if hp.include_dones: + (origx, Kmel_out, Ky1, Kdone_out, Ky2, Kmag_out, Ky3) = sess.run([g.origx, g.mel_output, g.y1, g.done_output, g.y2, g.mag_output, g.y3]) + plot_losses(config, Kmel_out, Ky1, Kdone_out, Ky2, Kmag_out, Ky3, gs) + else: + (origx, Kmel_out, Ky1, Kmag_out, Ky3) = sess.run([g.origx, g.mel_output, g.y1, g.mag_output, g.y3]) + plot_losses(config, Kmel_out, Ky1, None, None, Kmag_out, Ky3, gs) + elif (hp.train_form == 'Encoder'): + if hp.include_dones: + (origx, Kmel_out, Ky1, Kdone_out, Ky2) = sess.run([g.origx, g.mel_output, g.y1, g.done_output, g.y2]) + plot_losses(config, Kmel_out, Ky1, Kdone_out, Ky2, None, None, gs) + else: + (origx, Kmel_out, Ky1) = sess.run([g.origx, g.mel_output, g.y1]) + plot_losses(config, Kmel_out, Ky1, None, None, None, None, gs) + else: + (origx, Kmag_out, Ky3) = sess.run([g.origx, g.mag_output, g.y3]) + plot_losses(config, None, None, None, None, Kmag_out, Ky3, gs) + if ((epoch % config.checkpoint_interval) == 0): + tf.train.Saver().save(sess, checkpoint_path, global_step=gs) + if (hp.test_graph and (hp.train_form != 'Converter')): + if ((epoch % config.test_interval) == 0): + infolog.log('Saving audio') + origx = sess.run([g.origx]) + if (not config.load_converter): + wavs = synthesize.synthesize_part(g2, config, gs, origx, None) + else: + wavs = synthesize.synthesize_part(g2, config, gs, origx, g_conv) + plot_wavs(config, wavs, gs) + if (gs >= config.num_iterations): + break + else: + infolog.log('Saving audio') + gT = GraphTest(config=config) + with gT.graph.as_default(): + svT = tf.train.Supervisor(logdir=config.log_dir) + with svT.managed_session(config=session_config) as sessT: + origx = sessT.run([gT.origx]) + if (not config.load_converter): + wavs = synthesize.synthesize_part(g2, config, 0, origx, None) + else: + wavs = synthesize.synthesize_part(g2, config, 0, origx, g_conv) + plot_wavs(config, wavs, 0) + print('Done') +if (__name__ == '__main__'): + main() diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/.gitignore b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..757c4e3f3e44d00f72dea2a91582632c46df6831 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/.gitignore @@ -0,0 +1,14 @@ +# python related +*.pyc + +# C/C++ related +*.o +*.d +*.elf +*.bin +*.map + +# Temp files +*.swp +*.swo + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Quant_guide.md b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Quant_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..22debc304a8a019d5c5b14487c4bfde0d61468de --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Quant_guide.md @@ -0,0 +1,38 @@ +Deep learning models are typically trained with floating point data but they can quantized into integers during inference without any loss of performance (i.e. accuracy). Quantizing models includes quantizing both the weights and activation data (or layer input/outputs). In this work, we quantize the floating point weights/activation data to [Qm.n format](https://en.wikipedia.org/wiki/Q_(number_format)), where m,n are fixed within a layer but can vary across different network layers. + +## Quantize weights +Quantizing weights is fairly simple, as the weights are fixed after the training and we know their min/max range. Using these ranges, the weights are quantized or discretized to 256 levels. Here is the code snippet for quantizing the weights and biases to 8-bit integers. +```bash +min_wt = weight.min() +max_wt = weight.max() +#find number of integer bits to represent this range +int_bits = int(np.ceil(np.log2(max(abs(min_wt),abs(max_wt))))) +frac_bits = 7-int_bits #remaining bits are fractional bits (1-bit for sign) +#floating point weights are scaled and rounded to [-128,127], which are used in +#the fixed-point operations on the actual hardware (i.e., microcontroller) +quant_weight = np.round(weight*(2**frac_bits)) +#To quantify the impact of quantized weights, scale them back to +# original range to run inference using quantized weights +weight = quant_weight/(2**frac_bits) +``` + +## Quantize activation data +One approach for quantizing the activation data is to run inference on some representative input samples (or ideally, the entire dataset) and find the min/max range of each layer input/output. Using these ranges, the activation data can be quantized similar to the weights as shown in the above code snippet. Any outliers in the dataset may increase this range and may impact the accuracy, hence care must be taken in this approach. +Other approach is to insert the TensorFlow Op ["fake_quant_with_min_max_args"](https://www.tensorflow.org/api_docs/python/tf/fake_quant_with_min_max_args) after every operation (convolution, addition, multiplication or concatenation) and find the optimal power of 2 min,max ranges that maximize the accuracy. This same approach can also be used for quantizing the weights. Furthermore, this modified model with fake_quant_with_min_max_args Op and frozen min,max ranges can be used for retraining/fine-tuning, which may increase the accuracy as the network will adapt to quantization. + +## Quantizing KWS models +An example for quantizing DNN model is provided here. [quant_test.py](../quant_test.py) python script generates 8-bit quantized weights from the trained DNN model checkpoint and runs inference using quantized weights and floating-point activations on the entire dataset. It also dumps out the quantized weights into a text file (weights.h) which will be used while generating the binary for the Cortex-M board. +```bash +python quant_test.py --model_architecture dnn --model_size_info 144 144 144 --dct_coefficient_count 10 --window_size_ms 40 \ + --window_stride_ms 40 --checkpoint +``` +After quantizing the weights, next step is quantizing the activation data or layer input/outputs. [quant_models.py](../quant_models.py) has fake_quant_with_min_max_args Op inserted with its min/max ranges exposed as commmand line arguments. Optimal activation range that maximizes the accuracy can be progressively determined for each layer starting from the input layer to the output layer. For example, to quantize the neural network input layer data (i.e. MFCC features) to the range [-32,32) while the other layer activations are left as floating point, run `python quant_test.py --act_max 32 0 0 0 0`. After the activations of all layers are quantized and we are satisfied with the accuracy, the model can be deployed by calling the optimized neural network kernels from [CMSIS-NN](https://github.com/ARM-software/CMSIS_5) with appropriate scaling parameters obtained from the quantization steps. For example, from quantization sweeps we get the input to the first fully-connected layer in DNN model is of Q5.2 format or 2 bits after the decimal point (i.e. ranges from -32,31.75) and the expected output format for maximum accuracy is also Q5.2. Using quant_test.py, we get the quantized weights are of the format Q0.7 (i.e. in range -1,1) and the quantized biases have 8 bits for fractional point (i.e. range -0.5,0.5). So, the product (layer_input x weights) will have 9 bits in the fractional part (Q5.2 x Q0.7 = Qx.9) and biases need to be shifted left by 1 to get to the same representation (i.e. Qx.8<<1 = Qy.9). The layer output has 2 bits for fractional part (Q5.2), so the product (layer_input x weights) needs to be shifted right by 7 to get to Q5.2 format. + +## Fusing batch-norm layers +The parameters of batch normalization layers that follow the convolution or fully-connected layers (i.e. mean, variance, scale factor and offset factors: see [this](https://www.tensorflow.org/api_docs/python/tf/nn/batch_normalization) for more details) can be fused into the corresponding convn/fc layer weights and biases, which saves both memory and inference time. +```bash +# generate a new checkpoint (*_bnfused) with batch-norm fused to conv/fc layers +python fold_batchnorm.py --model_architecture ds_cnn --model_size_info 5 64 10 4 2 2 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 \ + --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 \ + --checkpoint work/DS_CNN/DS_CNN1/training/best/ +# continue with quantizing weights and activations as shown in previous steps, but with the new checkpoint diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/README.md b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c55b194a5f991b525e22ae2c78d3862eea5d8257 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/README.md @@ -0,0 +1,67 @@ +# Keyword Spotting on Arm Cortex-M boards. +The first step in deploying the trained keyword spotting models on microcontrollers is quantization, which is described [here](Quant_guide.md). This directory consists of example codes and steps for running a quantized DNN model on any Cortex-M board using [mbed-cli](https://github.com/ARMmbed/mbed-cli) and [CMSIS-NN](https://github.com/ARM-software/CMSIS_5) library. It also consists of an example of integration of the KWS model onto a Cortex-M development board with an on-board microphone to demonstrate keyword spotting on live audio data. + +## Get the CMSIS-NN library and install mbed-cli +Clone [CMSIS-5](https://github.com/ARM-software/CMSIS_5) library, which consists of the optimized neural network kernels for Cortex-M. +```bash +cd Deployment +git clone https://github.com/ARM-software/CMSIS_5.git +``` +Install [mbed-cli](https://github.com/ARMmbed/mbed-cli) and its python dependencies. +```bash +pip install mbed-cli +``` +## Build and run a simple KWS inference +In this example, the KWS inference is run on the audio data provided through a .h file. +First create a new project and install any python dependencies prompted when project is created for the first time after the installation of mbed-cli. +```bash +mbed new kws_simple_test --mbedlib +``` +Fetch the required mbed libraries for compilation. +```bash +cd kws_simple_test +mbed deploy +``` +Compile the code for the mbed board (for example NUCLEO\_F411RE). +```bash +mbed compile -m NUCLEO_F411RE -t GCC_ARM --source . \ + --source ../Source/KWS --source ../Source/NN --source ../Source/MFCC \ + --source ../Source/local_NN --source ../Examples/simple_test \ + --source ../CMSIS_5/CMSIS/NN/Include --source ../CMSIS_5/CMSIS/NN/Source \ + --source ../CMSIS_5/CMSIS/DSP/Include --source ../CMSIS_5/CMSIS/DSP/Source \ + --source ../CMSIS_5/CMSIS/Core/Include \ + --profile ../release_O3.json -j 8 +``` +Copy the binary (.bin) to the board (Make sure the board is detected and mounted). Open a serial terminal (e.g. putty or minicom) and see the final classification output on screen. +```bash +cp ./BUILD/NUCLEO_F411RE/GCC_ARM/kws_simple_test.bin /media//NODE_F411RE/ +sudo minicom +``` +## Run KWS inference on live audio on [STM32F746NG development kit](http://www.st.com/en/evaluation-tools/32f746gdiscovery.html) +This example runs keyword spotting inference on live audio captured using the on-board microphones on the STM32F746NG discovery kit. When performing keyword spotting on live audio data with multiple noise sources, outputs are typically averaged over a specified window to generate smooth predictions. The averaging window length and the detection threshold (which may also be different for each keyword) are two key parameters in determining the overall keyword spotting accuracy and user experience. +```bash +mbed new kws_realtime_test --create-only +cd kws_realtime_test +cp ../Examples/realtime_test/mbed_libs/*.lib . +mbed deploy +mbed compile -m DISCO_F746NG -t GCC_ARM \ + --source . --source ../Source --source ../Examples/realtime_test \ + --source ../CMSIS_5/CMSIS/NN/Include --source ../CMSIS_5/CMSIS/NN/Source \ + --source ../CMSIS_5/CMSIS/DSP/Include --source ../CMSIS_5/CMSIS/DSP/Source \ + --source ../CMSIS_5/CMSIS/Core/Include \ + --profile ../release_O3.json -j 8 +cp ./BUILD/DISCO_F746NG/GCC_ARM/kws_realtime_test.bin /media//DIS_F746NG/ +``` +## Build an example on [FRDM-K64F](https://os.mbed.com/platforms/FRDM-K64F/) using gcc and make +To build this example, clone CMSIS_5 repository and then `make`. This example is created by exporting a simple hello-world example from [mbed online compiler](https://os.mbed.com/compiler/) and editing the Makefile to incorporate the source files required for the keyword spotting example. +```bash +cd Deployment +# Clone CMSIS_5 repository (if not done already) +git clone https://github.com/ARM-software/CMSIS_5.git +cd Examples/simple_test_k64f_gcc +make -j 8 +# copy binary to the device +cp ./BUILD/simple_test_k64f_gcc.bin /media//DAPLINK/ +``` +**Note:** The examples provided use floating point operations for MFCC feature extraction, but it should be possible to convert them to fixed-point operations for deploying on microcontrollers that do not have dedicated floating point units. + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DNN/kws_dnn.cpp b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DNN/kws_dnn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e6f879784145d75ec844c3d64219065c51e7ba9 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DNN/kws_dnn.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "kws_dnn.h" + +KWS_DNN::KWS_DNN(int record_win, int sliding_win_len) +{ + nn = new DNN(); + recording_win = record_win; + sliding_window_len = sliding_win_len; + init_kws(); +} + +KWS_DNN::KWS_DNN(int16_t* audio_data_buffer) +{ + nn = new DNN(); + audio_buffer = audio_data_buffer; + recording_win = nn->get_num_frames(); + sliding_window_len = 1; + init_kws(); +} + +KWS_DNN::~KWS_DNN() +{ + delete nn; +} + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DNN/kws_dnn.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DNN/kws_dnn.h new file mode 100644 index 0000000000000000000000000000000000000000..79e7d8beca80e64b1eab0ba3998a36b7e8affcce --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DNN/kws_dnn.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __KWS_DNN_H__ +#define __KWS_DNN_H__ + +#include "kws.h" +#include "dnn.h" + +class KWS_DNN : public KWS { +public: + KWS_DNN(int recording_win, int sliding_window_len); + KWS_DNN(int16_t* audio_buffer); + ~KWS_DNN(); +}; + +#endif diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DS_CNN/kws_ds_cnn.cpp b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DS_CNN/kws_ds_cnn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c143823119a488a6f2cd1f2f4985342c938d5e1f --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DS_CNN/kws_ds_cnn.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "kws_ds_cnn.h" + +KWS_DS_CNN::KWS_DS_CNN(int record_win, int sliding_win_len) +{ + nn = new DS_CNN(); + recording_win = record_win; + sliding_window_len = sliding_win_len; + init_kws(); +} + +KWS_DS_CNN::KWS_DS_CNN(int16_t* audio_data_buffer) +{ + nn = new DS_CNN(); + audio_buffer = audio_data_buffer; + recording_win = nn->get_num_frames(); + sliding_window_len = 1; + init_kws(); +} + +KWS_DS_CNN::~KWS_DS_CNN() +{ + delete nn; +} + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DS_CNN/kws_ds_cnn.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DS_CNN/kws_ds_cnn.h new file mode 100644 index 0000000000000000000000000000000000000000..06c4dcfc3eea18f5c0c6a4ab295e6b510bea914a --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/KWS_DS_CNN/kws_ds_cnn.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __KWS_DS_CNN_H__ +#define __KWS_DS_CNN_H__ + +#include "kws.h" +#include "ds_cnn.h" + +class KWS_DS_CNN : public KWS { +public: + KWS_DS_CNN(int recording_win, int sliding_window_len); + KWS_DS_CNN(int16_t* audio_buffer); + ~KWS_DS_CNN(); +}; + +#endif diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/kws.cpp b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/kws.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88a708a48ef948a6ad0b47a704459ab65193f671 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/KWS/kws.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Description: Keyword spotting example code using MFCC feature extraction + * and neural network. + */ + +#include "kws.h" + +KWS::KWS() +{ +} + +KWS::~KWS() +{ + delete mfcc; + delete mfcc_buffer; + delete output; + delete predictions; + delete averaged_output; +} + +void KWS::init_kws() +{ + num_mfcc_features = nn->get_num_mfcc_features(); + num_frames = nn->get_num_frames(); + frame_len = nn->get_frame_len(); + frame_shift = nn->get_frame_shift(); + int mfcc_dec_bits = nn->get_in_dec_bits(); + num_out_classes = nn->get_num_out_classes(); + mfcc = new MFCC(num_mfcc_features, frame_len, mfcc_dec_bits); + mfcc_buffer = new q7_t[num_frames*num_mfcc_features]; + output = new q7_t[num_out_classes]; + averaged_output = new q7_t[num_out_classes]; + predictions = new q7_t[sliding_window_len*num_out_classes]; + audio_block_size = recording_win*frame_shift; + audio_buffer_size = audio_block_size + frame_len - frame_shift; +} + +void KWS::extract_features() +{ + if(num_frames>recording_win) { + //move old features left + memmove(mfcc_buffer,mfcc_buffer+(recording_win*num_mfcc_features),(num_frames-recording_win)*num_mfcc_features); + } + //compute features only for the newly recorded audio + int32_t mfcc_buffer_head = (num_frames-recording_win)*num_mfcc_features; + for (uint16_t f = 0; f < recording_win; f++) { + mfcc->mfcc_compute(audio_buffer+(f*frame_shift),&mfcc_buffer[mfcc_buffer_head]); + mfcc_buffer_head += num_mfcc_features; + } +} + +void KWS::classify() +{ + nn->run_nn(mfcc_buffer, output); + // Softmax + arm_softmax_q7(output,num_out_classes,output); +} + +int KWS::get_top_class(q7_t* prediction) +{ + int max_ind=0; + int max_val=-128; + for(int i=0;i + +#include "mfcc.h" +#include "float.h" + +MFCC::MFCC(int num_mfcc_features, int frame_len, int mfcc_dec_bits) +:num_mfcc_features(num_mfcc_features), + frame_len(frame_len), + mfcc_dec_bits(mfcc_dec_bits) +{ + + // Round-up to nearest power of 2. + frame_len_padded = pow(2,ceil((log(frame_len)/log(2)))); + + frame = new float[frame_len_padded]; + buffer = new float[frame_len_padded]; + mel_energies = new float[NUM_FBANK_BINS]; + + //create window function + window_func = new float[frame_len]; + for (int i = 0; i < frame_len; i++) + window_func[i] = 0.5 - 0.5*cos(M_2PI * ((float)i) / (frame_len)); + + //create mel filterbank + fbank_filter_first = new int32_t[NUM_FBANK_BINS]; + fbank_filter_last = new int32_t[NUM_FBANK_BINS];; + mel_fbank = create_mel_fbank(); + + //create DCT matrix + dct_matrix = create_dct_matrix(NUM_FBANK_BINS, num_mfcc_features); + + //initialize FFT + rfft = new arm_rfft_fast_instance_f32; + arm_rfft_fast_init_f32(rfft, frame_len_padded); + +} + +MFCC::~MFCC() { + delete []frame; + delete [] buffer; + delete []mel_energies; + delete []window_func; + delete []fbank_filter_first; + delete []fbank_filter_last; + delete []dct_matrix; + delete rfft; + for(int i=0;i left_mel && mel < right_mel) { + float weight; + if (mel <= center_mel) { + weight = (mel - left_mel) / (center_mel - left_mel); + } else { + weight = (right_mel-mel) / (right_mel-center_mel); + } + this_bin[i] = weight; + if (first_index == -1) + first_index = i; + last_index = i; + } + } + + fbank_filter_first[bin] = first_index; + fbank_filter_last[bin] = last_index; + mel_fbank[bin] = new float[last_index-first_index+1]; + + int32_t j = 0; + //copy the part we care about + for (i = first_index; i <= last_index; i++) { + mel_fbank[bin][j++] = this_bin[i]; + } + } + delete []this_bin; + return mel_fbank; +} + +void MFCC::mfcc_compute(const int16_t * audio_data, q7_t* mfcc_out) { + + int32_t i, j, bin; + + //TensorFlow way of normalizing .wav data to (-1,1) + for (i = 0; i < frame_len; i++) { + frame[i] = (float)audio_data[i]/(1<<15); + } + //Fill up remaining with zeros + memset(&frame[frame_len], 0, sizeof(float) * (frame_len_padded-frame_len)); + + for (i = 0; i < frame_len; i++) { + frame[i] *= window_func[i]; + } + + //Compute FFT + arm_rfft_fast_f32(rfft, frame, buffer, 0); + + //Convert to power spectrum + //frame is stored as [real0, realN/2-1, real1, im1, real2, im2, ...] + int32_t half_dim = frame_len_padded/2; + float first_energy = buffer[0] * buffer[0], + last_energy = buffer[1] * buffer[1]; // handle this special case + for (i = 1; i < half_dim; i++) { + float real = buffer[i*2], im = buffer[i*2 + 1]; + buffer[i] = real*real + im*im; + } + buffer[0] = first_energy; + buffer[half_dim] = last_energy; + + float sqrt_data; + //Apply mel filterbanks + for (bin = 0; bin < NUM_FBANK_BINS; bin++) { + j = 0; + float mel_energy = 0; + int32_t first_index = fbank_filter_first[bin]; + int32_t last_index = fbank_filter_last[bin]; + for (i = first_index; i <= last_index; i++) { + arm_sqrt_f32(buffer[i],&sqrt_data); + mel_energy += (sqrt_data) * mel_fbank[bin][j++]; + } + mel_energies[bin] = mel_energy; + + //avoid log of zero + if (mel_energy == 0.0) + mel_energies[bin] = FLT_MIN; + } + + //Take log + for (bin = 0; bin < NUM_FBANK_BINS; bin++) + mel_energies[bin] = logf(mel_energies[bin]); + + //Take DCT. Uses matrix mul. + for (i = 0; i < num_mfcc_features; i++) { + float sum = 0.0; + for (j = 0; j < NUM_FBANK_BINS; j++) { + sum += dct_matrix[i*NUM_FBANK_BINS+j] * mel_energies[j]; + } + + //Input is Qx.mfcc_dec_bits (from quantization step) + sum *= (0x1<= 127) + mfcc_out[i] = 127; + else if(sum <= -128) + mfcc_out[i] = -128; + else + mfcc_out[i] = sum; + } + +} + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/MFCC/mfcc.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/MFCC/mfcc.h new file mode 100644 index 0000000000000000000000000000000000000000..03992bf72f2ed6ac78c426e8e8b45a7cbe61edce --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/MFCC/mfcc.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __KWS_MFCC_H__ +#define __KWS_MFCC_H__ + +#include "arm_math.h" +#include "string.h" + +#define SAMP_FREQ 16000 +#define NUM_FBANK_BINS 40 +#define MEL_LOW_FREQ 20 +#define MEL_HIGH_FREQ 4000 + +#define M_2PI 6.283185307179586476925286766559005 + +class MFCC{ + private: + int num_mfcc_features; + int frame_len; + int frame_len_padded; + int mfcc_dec_bits; + float * frame; + float * buffer; + float * mel_energies; + float * window_func; + int32_t * fbank_filter_first; + int32_t * fbank_filter_last; + float ** mel_fbank; + float * dct_matrix; + arm_rfft_fast_instance_f32 * rfft; + float * create_dct_matrix(int32_t input_length, int32_t coefficient_count); + float ** create_mel_fbank(); + + static inline float InverseMelScale(float mel_freq) { + return 700.0f * (expf (mel_freq / 1127.0f) - 1.0f); + } + + static inline float MelScale(float freq) { + return 1127.0f * logf (1.0f + freq / 700.0f); + } + + public: + MFCC(int num_mfcc_features, int frame_len, int mfcc_dec_bits); + ~MFCC(); + void mfcc_compute(const int16_t* data, q7_t* mfcc_out); +}; + +#endif diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn.cpp b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d87046b7a9246c99aa473f5e0439ea6c6dc6bacd --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Description: Keyword spotting DNN model example code + */ + +/* Network Structure + + 10x25 input features + | + IP1 : Innerproduct (weights: 250x144) + | + IP2 : Innerproduct (weights: 144x144) + | + IP3 : Innerproduct (weights: 144x144) + | + IP4 : Innerproduct (weights: 144x12) + | + 12 outputs + +*/ + +#include "dnn.h" + +const q7_t DNN::ip1_wt[IP1_WT_DIM]=IP1_WT; +const q7_t DNN::ip1_bias[IP1_OUT_DIM]=IP1_BIAS; +const q7_t DNN::ip2_wt[IP2_WT_DIM]=IP2_WT; +const q7_t DNN::ip2_bias[IP2_OUT_DIM]=IP2_BIAS; +const q7_t DNN::ip3_wt[IP3_WT_DIM]=IP3_WT; +const q7_t DNN::ip3_bias[IP3_OUT_DIM]=IP3_BIAS; +const q7_t DNN::ip4_wt[IP4_WT_DIM]=IP4_WT; +const q7_t DNN::ip4_bias[OUT_DIM]=IP4_BIAS; + +DNN::DNN() +{ + scratch_pad = new q7_t[SCRATCH_BUFFER_SIZE]; + ip1_out = scratch_pad; + ip2_out = ip1_out+IP1_OUT_DIM; + ip3_out = ip1_out; + vec_buffer = (q15_t*)(ip1_out+IP1_OUT_DIM+IP2_OUT_DIM); + frame_len = FRAME_LEN; + frame_shift = FRAME_SHIFT; + num_mfcc_features = NUM_MFCC_COEFFS; + num_frames = NUM_FRAMES; + num_out_classes = OUT_DIM; + in_dec_bits = MFCC_DEC_BITS; +} + +DNN::~DNN() +{ + delete scratch_pad; +} + +void DNN::run_nn(q7_t* in_data, q7_t* out_data) +{ + // Run all layers + + // IP1 + arm_fully_connected_q7(in_data, ip1_wt, IN_DIM, IP1_OUT_DIM, 1, 7, ip1_bias, ip1_out, vec_buffer); + // RELU1 + arm_relu_q7(ip1_out, IP1_OUT_DIM); + + // IP2 + arm_fully_connected_q7(ip1_out, ip2_wt, IP1_OUT_DIM, IP2_OUT_DIM, 2, 8, ip2_bias, ip2_out, vec_buffer); + // RELU2 + arm_relu_q7(ip2_out, IP2_OUT_DIM); + + // IP3 + arm_fully_connected_q7(ip2_out, ip3_wt, IP2_OUT_DIM, IP3_OUT_DIM, 2, 9, ip3_bias, ip3_out, vec_buffer); + // RELU3 + arm_relu_q7(ip3_out, IP3_OUT_DIM); + + // IP4 + arm_fully_connected_q7(ip3_out, ip4_wt, IP3_OUT_DIM, OUT_DIM, 0, 6, ip4_bias, out_data, vec_buffer); + +} + + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn.h new file mode 100644 index 0000000000000000000000000000000000000000..697d1c0a1849c9e98d48a74ea5525e4d9d121b7c --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __DNN_H__ +#define __DNN_H__ + +#include "nn.h" +#include "dnn_weights.h" +#include "arm_nnfunctions.h" +#include "arm_math.h" + +/* Network Structure + + 10x25 input features + | + IP1 : Innerproduct (weights: 250x144) + | + IP2 : Innerproduct (weights: 144x144) + | + IP3 : Innerproduct (weights: 144x144) + | + IP4 : Innerproduct (weights: 144x12) + | + 12 outputs + +*/ + +#define SAMP_FREQ 16000 +#define MFCC_DEC_BITS 2 +#define FRAME_SHIFT_MS 40 +#define FRAME_SHIFT ((int16_t)(SAMP_FREQ * 0.001 * FRAME_SHIFT_MS)) +#define NUM_FRAMES 25 +#define NUM_MFCC_COEFFS 10 +#define MFCC_BUFFER_SIZE (NUM_FRAMES*NUM_MFCC_COEFFS) +#define FRAME_LEN_MS 40 +#define FRAME_LEN ((int16_t)(SAMP_FREQ * 0.001 * FRAME_LEN_MS)) + +#define IN_DIM (NUM_FRAMES*NUM_MFCC_COEFFS) +#define OUT_DIM 12 +#define IP1_OUT_DIM 144 +#define IP2_OUT_DIM 144 +#define IP3_OUT_DIM 144 +#define IP1_WT_DIM (IP1_OUT_DIM*IN_DIM) +#define IP2_WT_DIM (IP2_OUT_DIM*IP1_OUT_DIM) +#define IP3_WT_DIM (IP3_OUT_DIM*IP2_OUT_DIM) +#define IP4_WT_DIM (OUT_DIM*IP3_OUT_DIM) +#define SCRATCH_BUFFER_SIZE (2*(IN_DIM+3*IP1_OUT_DIM)) + +class DNN : public NN { + + public: + DNN(); + ~DNN(); + void run_nn(q7_t* in_data, q7_t* out_data); + + private: + q7_t* scratch_pad; + q7_t* ip1_out; + q7_t* ip2_out; + q7_t* ip3_out; + q15_t* vec_buffer; + static q7_t const ip1_wt[IP1_WT_DIM]; + static q7_t const ip1_bias[IP1_OUT_DIM]; + static q7_t const ip2_wt[IP2_WT_DIM]; + static q7_t const ip2_bias[IP2_OUT_DIM]; + static q7_t const ip3_wt[IP3_WT_DIM]; + static q7_t const ip3_bias[IP3_OUT_DIM]; + static q7_t const ip4_wt[IP4_WT_DIM]; + static q7_t const ip4_bias[OUT_DIM]; + +}; + +#endif diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn_weights.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn_weights.h new file mode 100644 index 0000000000000000000000000000000000000000..1e78d842cc5c2e77b190a943daaad667a7fd805f --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DNN/dnn_weights.h @@ -0,0 +1,8 @@ +#define IP1_WT {12, -7, 24, -7, -8, -10, 15, -17, -19, -1, -9, 9, 14, -7, -9, -19, -10, -27, -8, 14, -5, -3, 9, -3, 5, -2, 0, -7, 0, 14, -10, -13, 20, -3, -2, -6, 5, 0, -2, 19, 3, -5, 12, 8, 4, -4, 11, 3, 10, 9, 13, -11, 1, 5, -13, -2, 5, 1, 22, -2, -5, 2, 5, 14, 6, 6, 14, -16, 2, 12, 1, -12, 18, 13, 5, -2, -5, 15, 26, -9, 0, 3, 19, -7, 6, -8, 13, -4, 39, 4, 20, -6, -1, -29, -7, 19, 3, -3, 37, 17, -3, 3, -11, -29, -23, 15, 18, -2, 22, 2, -10, -6, -11, -8, -21, 11, 14, -1, 19, -10, -14, 0, 14, -9, -25, 11, 6, 11, -5, -17, -12, 6, 20, -6, -10, 10, -13, 8, -22, -12, 1, 7, 7, -4, -11, 27, 7, -2, -9, -12, 21, 7, 6, -15, 7, 27, -5, -11, -17, -20, 10, 21, -1, 4, -5, 12, -16, -6, -8, -23, 14, -5, 4, -3, -9, 24, -9, -3, -14, -7, -15, -5, -23, 3, 13, 7, -10, 0, -2, 6, 5, -2, -29, -12, -16, 7, -8, 2, 13, 12, -7, -4, -13, -17, -20, -12, -16, 10, 16, 20, -1, 5, -11, 1, -11, -20, -10, 18, 24, 7, -5, 5, -8, 1, -24, -4, 2, 9, 4, 14, 0, 7, -14, -9, -23, -14, -16, 3, 12, 3, -8, 10, 2, -7, -10, 11, -15, -7, -1, -1, 5, 8, 3, -13, -8, -8, -9, 18, -3, -5, 9, 4, -5, 3, -1, 0, -6, -5, -7, -12, 4, -13, -2, 11, -8, 0, 8, 3, -7, -11, -8, -5, 16, -6, 1, 5, 11, 13, -15, 5, 3, -12, 2, 2, 7, 15, 41, -6, 3, 3, 5, 4, -5, -16, 18, 13, 40, -4, -17, 27, 0, 18, 8, -20, 0, 15, 28, -16, 7, 18, -8, 6, -4, -24, 10, 9, 5, -12, 1, 25, 4, -4, 13, -11, 17, 3, 12, -3, 22, 6, -4, -1, -1, -5, 7, -14, 17, -1, 13, 11, 0, -7, 18, -11, -2, -9, 6, -5, 0, 20, -10, -25, 17, -9, -11, -8, -11, -12, 18, 32, -11, -9, 13, -24, -31, -15, 10, 7, 17, 5, 17, -11, 13, -21, -40, 2, 6, 7, -18, 19, -12, -15, -18, -1, -12, 1, 12, 5, -33, -4, -5, 14, -39, 5, 20, 18, -9, -14, -12, 4, 16, 20, -32, 9, 49, 8, -44, -23, -3, 0, 15, 25, -28, 14, 41, -11, -39, 1, -15, -15, 0, 3, -22, 6, 30, -25, -5, -2, 13, -22, 3, -15, -23, 34, 22, -2, 0, 6, -3, -23, -11, -15, 2, 35, -5, -10, -5, -4, -10, -20, 0, 3, 17, 16, -15, -3, 6, -5, -3, 0, -5, -5, -7, 14, 1, 4, -15, 9, -15, 10, -5, 13, -5, 17, -6, 17, 6, 6, -15, -1, -7, 1, 7, 23, 2, 8, -2, 12, 6, 1, -5, 3, 23, 13, -19, 4, -8, 6, 18, -3, 8, 8, 20, 1, -12, 16, -1, 4, 9, 4, 0, 18, 13, 4, -7, -5, 12, 14, 26, -5, -2, -1, -5, 8, -8, -8, -1, 5, 11, 3, 5, 13, 1, -4, 13, -2, -14, -11, 10, -7, -9, -6, -17, 14, 18, -19, -3, -14, 13, 6, 6, -13, -16, -3, 10, 0, 14, -4, -5, 6, -7, -27, -43, 8, -1, 7, 33, -9, -24, 6, 17, -16, -20, -6, -34, -11, 20, 3, -33, -3, 12, 17, -1, -23, -33, -18, 19, 28, -50, -16, 2, 17, 3, -26, -24, -20, -20, 15, -40, -16, -6, 11, 7, -15, 12, -14, -3, 6, -33, 4, -13, 3, -14, -15, 16, -6, 0, 20, -13, 13, -6, -16, 0, -1, 5, -16, 27, 17, -17, 8, 12, -4, 10, 21, -28, 5, 13, -9, -22, -15, 0, 4, 5, 34, -32, 2, -3, -14, -8, 15, -1, 6, 21, 13, 5, 0, -9, -12, -10, 18, -6, 5, -10, 12, -6, 11, 3, -18, -7, 11, -8, -12, -12, 18, -6, 10, 0, 3, 9, 17, -14, 6, -10, -7, 14, 5, 10, -10, 14, -1, 14, -9, 8, -8, 13, -2, 7, 2, 3, 10, -10, -3, 3, 9, 1, 7, -2, 9, 15, 20, 16, -5, 0, 0, 12, 11, 4, -9, 8, 14, -13, 0, 1, 5, 7, -9, 4, 4, -4, 8, 2, -3, 6, -5, 4, 11, -5, -4, 3, 10, 13, 19, 14, 12, -5, -12, -3, -2, 9, 15, -2, 7, 2, 10, -11, -17, 0, 5, 1, 1, 5, -11, -16, 18, -4, 2, 28, -5, 5, 17, 12, 1, -4, 26, -8, 5, 20, 9, 3, 11, 7, -14, 1, 29, -14, 10, 4, 7, 7, 15, 6, -7, 17, 6, -17, -3, 0, -15, 13, 23, -16, -8, 12, 2, -12, 8, -4, 3, 17, 23, -1, -14, -16, 19, 0, -2, 20, 17, 16, 0, 9, -2, 1, -12, 13, -17, 16, 3, 12, 11, 8, 6, -2, -6, 8, 6, 18, 13, 16, 3, 0, -16, 18, -17, -1, 9, 18, 18, -3, 13, -8, -3, 4, -14, 3, -10, 29, 16, 11, 1, -8, -32, 5, 8, 8, -4, 17, 4, -16, 9, -4, 1, -15, -9, -1, -13, 3, 7, -22, 2, 13, 17, -17, -1, 0, 13, 1, 1, -37, 7, 5, 8, -5, -6, 21, 11, 6, -3, -12, 15, -16, -13, -12, 4, 13, 22, -3, -9, -17, 8, -14, -24, -4, 7, 12, 6, 0, -5, -2, -7, -10, -12, -2, 17, 6, 21, -11, 16, 0, 7, -16, -9, -5, 7, -4, 11, -12, -3, 1, 9, -15, 9, 2, 10, 11, 16, -19, 0, 8, 2, 4, -2, 0, -15, 23, 2, -13, 5, -10, 10, 8, 16, -3, -15, -6, 10, -8, 9, -15, -6, 7, 9, -3, -2, 4, 3, -11, 1, 0, -15, 16, 20, -1, 2, 7, -3, 8, -7, 11, -4, 2, 0, -3, -14, -5, -7, 20, -7, 10, 9, 9, -8, 8, -1, -8, -6, 2, 0, 0, 11, 5, 2, 4, -7, -22, 0, 12, 8, -3, 8, -2, 15, -2, 7, -40, -2, 11, 20, 5, 21, 16, 15, -18, 14, -37, 2, 28, 27, 3, -10, -7, 2, -28, 14, 7, 14, 2, -15, -11, 8, 3, 4, -7, 22, 10, 21, -4, -17, -8, 16, 2, 6, -8, 14, 28, 2, 10, -20, -19, 0, -9, 8, -18, 19, 22, -1, 16, -4, -9, 11, 5, -13, 7, 13, 24, 3, -17, -12, 16, 9, -10, 4, 13, -3, 10, -7, -24, -4, 5, 12, -13, 3, -2, -2, 16, -4, -14, 2, 12, -8, -8, -17, 18, -11, 21, -8, 3, 0, 17, -4, 2, -23, 21, -20, 18, -3, 16, -20, 27, -3, -11, -18, 28, -17, -17, 2, -2, -19, 20, 3, 9, -11, 34, -7, -32, -27, -14, 3, 8, -1, 6, 5, 38, -5, -55, -17, -21, 13, -22, -23, 13, -8, 18, 9, -49, -16, -12, 11, -27, -17, 20, -5, -19, 14, -19, -4, 9, 13, -16, -17, -1, 5, -39, 7, 15, -1, 1, 10, -2, -10, -6, 1, -19, -3, 33, 4, 1, -4, -5, -6, -8, 13, -28, -11, 16, 5, 5, -9, 14, -4, -11, 6, -10, -12, 22, 3, 15, -9, 3, 12, -1, 2, -8, -1, 4, 7, 0, 1, 3, 9, -6, 3, 9, 13, 0, 9, -3, 4, 13, 4, -1, 8, 18, 6, -15, 3, -16, -3, 9, -5, -10, 10, 11, 10, -5, -17, 5, -1, -2, -15, 14, -5, 16, 6, -13, -3, -11, -14, -4, -5, 3, -1, 3, 5, -4, -9, -4, 8, 4, 0, -14, -4, 9, 3, 6, -14, 7, 0, 2, 5, -11, -17, -19, -10, 3, 18, -11, 18, 5, -10, -3, 7, -19, -4, 34, 8, -13, 25, 14, -25, 11, 21, -6, -28, 37, 6, -15, 2, -7, -26, -6, 22, -1, -20, 30, 9, -20, 12, -6, -23, 10, 22, -7, -24, 26, 8, -3, -3, -2, -10, 1, 9, -16, -27, 40, 10, 21, -8, -16, 6, -2, -16, -10, -3, 43, 2, -6, 1, -13, 10, 7, -17, -23, -14, 26, 10, -7, -7, -14, -12, 11, -10, -7, 12, 15, 10, -6, -10, -14, 1, -3, -1, -2, 2, -19, -3, -17, 12, -13, 15, 15, 8, 9, 30, -8, -19, -13, 11, -16, 3, -11, 9, -5, 40, -4, -10, -7, -3, -5, -16, 7, 9, 20, 34, 9, -5, 9, 7, -21, -9, -1, -14, -1, 6, 1, -27, 11, -4, -6, 5, -9, -2, 17, 9, 3, -26, 18, -6, -4, -2, -3, 3, 14, 4, 6, -3, 3, 2, -3, -3, 3, -11, -1, -3, -12, 2, 17, 1, 0, 5, -15, -6, -4, 12, 1, -5, -8, 5, 6, -4, -2, -9, -2, -9, -10, -2, 7, -7, -5, 6, 11, 5, -2, 10, -11, 3, 2, 10, -6, 10, -15, -11, 7, 20, 14, -16, -2, -5, -7, -1, 10, -7, -5, -2, 17, 0, -3, -17, 5, -14, -5, 4, -18, -11, 7, 19, -14, -4, -3, -30, 15, -8, -6, -8, 1, 6, -13, -4, 4, -21, 14, 2, 7, -12, -18, 12, -24, 5, 23, -14, -9, 1, 13, -20, -25, 6, -16, 16, 15, 6, -10, 10, 11, -27, -6, 11, -17, 0, 30, 11, 4, 7, 4, -30, -15, 21, -4, -10, 11, 16, 4, 8, 14, -23, -13, 23, 8, 1, 7, 19, 3, 5, -1, -14, -11, 27, 12, 4, 2, 27, -7, -14, -8, -3, 0, 18, 8, -11, -6, 14, -6, -5, 2, 8, 9, -4, 10, 6, -7, 9, -18, -34, 13, 26, 12, -11, 24, 2, 7, 15, -8, -15, 10, 29, -20, -19, 38, 19, 15, 12, 12, -17, 1, 37, -30, -15, 38, 4, -6, -13, -11, -4, -17, 41, -26, -18, 11, 3, 3, -17, 4, -7, -13, 16, 9, -10, 16, -5, -6, -28, 8, 3, -15, -1, 19, 5, -16, 1, -5, -14, 13, 15, -17, -31, 7, 12, -24, -13, 10, -20, -3, 20, -3, -24, 19, 18, -15, -22, 8, -10, 11, 14, -9, -24, 6, 11, -17, -5, 8, -2, 6, 25, -6, -10, 15, 13, -28, 7, 1, 2, -5, 2, -2, 7, 13, 3, -14, 4, 1, 11, -3, 0, 5, -4, -4, 4, -6, 10, 4, 3, 3, -7, -6, 3, 8, 7, -9, 9, -4, 0, -7, -1, -5, -3, 7, 7, 0, 2, 3, -15, 5, -2, 3, -12, 12, -6, 27, -7, 0, 5, -8, -11, 6, 8, 2, 10, -1, 6, 9, -5, -9, 0, -8, 8, 0, -4, 11, 9, 13, -3, -8, 7, -19, -3, 20, 14, 18, 7, 10, 10, 11, 1, -28, -8, 18, 5, 3, 5, 4, 0, 8, 12, -13, 6, -1, 8, 19, -8, -5, 1, -12, -1, 1, 9, 12, 7, 3, 9, -6, 0, 1, -7, 7, 11, 21, -1, 7, -17, -5, -7, 7, 2, 4, 26, -1, 2, 9, -4, -27, -2, 9, -8, -23, 15, 1, -3, 10, 17, -22, -10, -4, -16, -10, 1, -5, 20, 23, 7, -13, -28, 5, -6, 14, 0, -39, 36, -1, 7, 0, -9, 1, 22, 40, -27, -54, 29, -8, -2, 16, 23, -3, 31, 53, -30, -63, 10, 11, -29, 18, 17, 8, 24, 28, -13, -34, 25, 11, -19, -16, 18, 6, -10, -12, 5, 10, 32, 19, -15, 4, 2, -15, -23, -23, 17, 17, 5, 11, -19, 10, -4, -1, -24, -8, 14, 15, 5, 10, 10, -3, 13, 8, -1, 3, 17, 18, 1, 1, -4, 7, 3, 3, -3, 2, 7, 7, -5, 6, 4, -3, -11, 11, 6, 16, -7, -1, 3, -3, 4, -2, -12, -7, 15, -9, -8, 11, -2, 14, 1, -18, -10, 6, -1, -13, -2, 15, 0, 4, 15, -9, -6, -6, -12, -23, 4, 3, 5, 6, 3, 5, -12, -11, 18, 5, 16, -10, 5, -2, 8, 0, -3, -5, 10, -25, 30, 10, 16, 6, 21, -1, 11, 6, 1, -29, 32, 5, 5, 21, -4, 3, -5, 15, -9, -24, 20, 6, -2, 18, -10, 0, -2, 17, -20, -30, 15, -22, 0, 20, -16, 0, -2, 12, -3, -15, 3, -43, -7, 2, -12, -14, -15, 3, 19, -15, -1, -45, -11, -6, 9, -19, -17, -20, 9, 12, -13, -14, -5, -6, 30, -13, -2, -25, -8, 11, -22, 13, 15, -4, 26, 1, 0, 1, 1, -10, -15, 25, 12, -3, 10, 1, 0, 8, -9, 2, -20, 33, -9, -28, 8, 18, -15, 17, 18, -19, -1, 23, -22, -3, 8, 22, -13, 2, -2, -17, 16, 16, -17, 27, 5, -5, -16, -10, -2, -12, -3, 8, 3, 20, 5, -10, -8, -2, -2, 7, 1, -3, -10, 0, -9, -7, 14, -4, 3, 31, 6, -6, -4, -9, -15, 13, 9, 8, 16, 6, -3, 1, -5, 8, -12, 0, 7, -14, -9, 18, 14, -1, 0, -5, -11, 2, 7, 2, -14, 14, 0, 11, -3, -11, -8, -3, 5, -8, -5, 12, 12, 10, 9, -2, 0, 3, 0, 3, -12, 3, -2, 7, -8, 12, 5, 1, 7, 7, -13, -5, 1, 11, 21, 12, -9, 4, -2, -5, -3, -3, 6, 9, 2, 10, -3, 0, 5, -1, -5, 6, -10, -3, 1, 6, -14, -2, 1, 1, 0, 17, -13, -7, -15, 0, -17, 3, -3, -3, 7, -20, -6, 9, 5, 11, 21, -19, -6, 11, -12, -6, -11, 18, 8, 2, 15, -3, -16, 17, 8, 4, -2, 14, 11, -13, 19, -1, -18, -12, 8, 0, 0, -6, 6, 13, 6, 7, -11, -14, -2, 3, 15, -16, 5, 5, 12, 14, 1, -16, -23, 12, 2, 10, 17, 2, -2, 7, -4, -7, -13, -12, -5, 10, 13, -14, 10, 4, 22, 5, 12, -16, 3, 19, 7, -15, -3, 1, -2, -1, 3, -7, -4, 19, -4, 1, 2, 5, 5, -12, 9, -2, -8, 0, -6, 16, 9, 3, -4, -16, -2, 15, 18, 18, 7, -5, -18, 17, 0, -3, -10, 21, 6, 27, -4, -26, -11, 14, 7, -4, -12, 6, 2, 20, -8, -8, -2, 15, 17, 21, -8, -10, 0, -9, -1, 5, 14, -10, -14, 26, 6, -26, -3, -19, -2, 17, 8, -8, -14, -1, 6, -2, 7, -6, 3, 7, -5, -5, -3, -9, 2, -4, 12, -9, 2, 0, 5, 11, 10, -12, -14, 15, 6, -6, -13, -16, 4, 14, 20, -2, -4, 15, -1, -1, 0, -2, 5, 5, 5, -13, 1, -1, -11, 14, 9, -4, 2, 9, 10, 11, 19, -3, -19, 4, -5, -7, 1, 11, 0, 14, 6, -4, -2, 5, -17, 1, 11, 13, -8, 15, -3, -2, 10, -2, -12, 14, 15, 10, -11, -7, 7, 10, 13, -1, -18, 9, 8, -6, 1, 13, -7, 8, 4, -9, 1, 18, 7, -2, 0, -4, 8, -3, 2, 1, 6, -3, 6, 7, 5, 0, -10, 3, 2, -11, 12, -6, 9, -2, 14, 7, -4, -15, 16, 8, 10, -1, 2, 1, 13, -14, -8, -20, 2, -4, 3, -5, -6, -4, 12, -3, -11, -1, 5, 5, -17, -4, 8, 8, -1, -9, -7, 5, 2, 1, -4, 11, 6, 1, -8, -13, -27, 6, -13, 13, 8, 10, 10, 11, 15, 10, -14, 9, -2, 0, -10, 17, -6, 15, -1, 10, -33, 19, -1, -8, -12, 31, -4, -1, 21, 13, -29, -4, -14, -9, -17, 32, 12, -1, 14, 6, -25, 7, -19, 0, -5, 30, 15, 0, 6, 14, 4, -13, -20, 8, -22, -11, 15, 16, 14, -2, 0, 16, -16, 7, -8, -13, 4, 8, 4, 1, 22, 11, -14, -1, -26, -15, -1, 7, 5, 5, 22, 13, 16, 17, -13, -9, 1, -10, -2, 10, 8, 4, 11, 15, -21, 0, 5, -27, -5, 2, 4, -8, 21, 3, -9, -18, 3, -14, -20, 5, 16, 1, 6, 9, 4, -28, 11, -10, -17, -7, 25, 4, 3, 16, 2, -41, -2, 9, -12, -16, 39, 3, -4, 3, 21, -28, -4, -3, -2, 3, 23, 7, 2, 3, 11, -9, -17, -4, 11, -16, 11, 1, 6, -14, 19, 6, 1, -8, 16, 1, -1, -7, 11, -3, 18, 14, 9, -2, -10, -1, 2, -13, 3, -7, 4, 6, 2, -13, 8, -3, -11, -12, 17, -7, 16, -4, -6, 7, -1, -11, -4, -9, 3, -5, 4, -6, -14, -2, 0, -7, -8, 2, 1, -8, -9, -7, -15, 9, 15, -6, 8, 2, -1, 9, -10, -20, 9, 0, 26, -6, 9, -10, -2, 2, -30, -12, 14, -6, 3, 6, 7, -18, 10, 12, -24, 11, 2, -8, 9, 8, -14, 3, 2, 10, 3, 36, -15, -17, 0, -4, -33, 0, 1, 7, 4, 10, -18, 2, 0, 9, -30, -12, 16, -12, 24, 14, -8, -3, 5, -12, -13, 6, -1, 0, 22, 8, -5, -9, 11, 2, -28, 7, 4, -4, 7, 14, 7, -9, -2, -3, 1, 20, 7, -10, 1, -2, 6, 6, 0, -2, -10, 23, 11, -1, -14, -12, -1, -4, -5, -9, 9, 9, 21, 10, 0, -4, -1, -8, 8, 3, -15, -10, 16, 19, 13, 27, -8, -7, 9, -3, -32, -2, 1, 1, 20, 31, -15, -7, 5, 19, -18, 17, 9, -32, -1, 3, -5, -2, -18, 12, 15, 15, 7, -30, -16, -8, 3, -3, -17, 13, 25, 13, 2, -11, -36, -17, 16, 6, -7, -16, 12, -5, -20, 17, -27, -13, 22, 27, 0, -17, 24, -20, -20, 26, -9, -5, 11, 13, -4, -1, 13, -15, -18, 0, 2, 0, -7, 16, -12, 1, 37, -15, -17, -11, 4, 20, 5, 14, 16, 17, 38, 5, -4, 2, -6, 10, 9, -7, 8, 10, 23, 9, -9, -33, 16, -1, 2, -12, -3, 5, 0, 25, -6, -29, 3, -7, -8, -24, -6, 9, -13, -7, 1, 12, -3, 18, -3, 1, -13, 3, -4, -15, 12, 32, -15, 8, 12, -2, -12, -3, 13, -2, -10, 27, -14, 8, 8, -4, -12, 6, 15, 9, -5, 14, -16, 2, 7, 10, -14, 21, 16, 30, 5, -10, -27, -20, 0, 10, -24, 0, 7, 31, -10, -11, -22, -28, -7, 13, -22, -8, 8, 18, 7, -12, -17, -35, -2, 4, 1, 10, 2, 20, 7, -5, -12, -20, -9, -12, 3, -7, 0, -2, -6, 3, -2, -22, -2, -9, 10, -4, 12, -19, -19, 11, 9, 2, 12, 9, 10, 14, 0, -29, -15, 17, 16, -2, 9, -6, 4, 8, 8, -13, -26, 16, 33, -17, -12, 2, 3, -9, 17, -1, -16, -1, 21, -12, -1, 2, 4, -13, 6, 7, 15, -6, 31, -3, 12, 4, 14, -16, -22, -5, 12, -2, 26, 0, 2, -7, 7, -15, -22, -18, 12, 20, 13, -5, -11, -18, -13, 16, -11, -15, 5, 14, 13, 1, -11, -27, -12, 12, 8, 16, -14, 4, 8, -6, 12, -23, 0, 19, -1, -1, -3, 3, -13, 10, 6, -12, -11, -5, -10, -2, -7, 1, -8, 12, -2, 0, -15, -10, -18, -1, 4, -1, 8, -1, 20, 12, 1, -12, 1, -7, 9, -1, 0, 6, -6, 11, 13, -3, -2, 4, -7, 2, 8, 11, -12, 4, 0, -2, 9, -10, 11, 5, 7, 11, 3, 4, 7, -3, -4, 0, 7, 9, 13, 18, -2, 0, -5, -3, 7, -16, -11, 14, 8, -4, -6, 4, 6, -2, 0, -1, -1, -4, 16, 1, -5, -14, -1, 2, 7, -6, 2, -8, 7, -14, 6, -14, 6, 11, -7, 3, -3, 29, 10, 4, 1, -9, -1, 9, 14, 13, -4, 21, 13, 0, -13, -15, 10, -2, -16, 7, -6, 7, -5, 0, 7, -4, -14, -21, -9, -9, 5, 19, -2, -11, -2, 6, 0, 10, -9, -3, 21, 10, 18, 8, -13, -11, -3, -2, -22, 5, 33, -3, -11, -6, -15, 4, 1, 17, 8, 16, 13, -19, -17, -33, 1, -4, -9, 14, 19, 16, 1, -23, -13, -20, 12, -26, -31, 6, 25, -4, -7, 2, -4, -22, 39, -27, -20, 6, 4, -32, 3, 18, 2, 11, 33, -9, -16, -16, -20, -14, -27, 18, -2, -4, 26, 9, -18, -7, -3, -19, -10, 6, 4, -13, 11, 24, 2, -4, 1, -11, -11, -13, 10, 5, 17, 10, 14, 3, -15, -9, 6, -17, -13, 29, 3, 9, 10, -1, -2, 1, 10, -15, 4, 18, 9, 5, 6, -3, -3, -6, 5, -22, 1, 6, 15, -2, 8, -5, -16, 4, 3, -17, 2, 13, -6, -6, 15, -9, 2, 16, 14, -14, -2, 6, -6, 1, 9, 13, -1, 2, 16, 3, 6, -7, -14, -15, 7, 2, 0, 4, 13, -13, -2, -14, -12, 4, -1, -7, 11, -3, 3, -9, -7, -13, -4, -3, 11, -9, 6, 0, 0, -7, -8, 13, -19, -2, 2, -3, -9, 3, -2, -8, -6, 4, -13, -14, 2, 4, 0, 1, -7, 9, -6, -1, -10, 9, 4, -3, -4, -5, 10, -5, -2, 5, -9, 3, -11, -8, 10, -6, -12, 12, 6, 13, 0, -2, -2, -9, -12, -5, 3, 6, 9, 17, -1, 8, 0, 7, -11, 0, 5, -2, -4, 4, 0, -9, 3, -9, -9, -3, 2, 14, -11, 0, -14, 9, 2, 6, -1, -11, 0, -6, -1, 12, -7, 8, 18, -4, 11, -8, -6, -14, -4, 3, 1, -8, 15, -1, -9, -3, -7, -30, 11, 14, 4, -12, -5, 12, -8, 27, 6, -37, 10, -5, 2, 2, 10, -5, 10, 30, 10, -25, 4, -29, -22, -7, 9, -11, 24, 31, 15, -12, -3, -29, -8, 2, 24, -12, 20, -3, 10, 36, 7, -26, 12, 16, 27, -7, 11, -36, -21, 63, -8, -5, 7, 24, 13, 15, -4, -33, -23, 28, -12, 17, 7, 7, -12, 6, -6, 4, -14, -23, -2, 29, 17, 4, -17, 6, -10, 23, -10, -27, -33, -2, 9, 11, 3, -3, -11, 27, -9, -4, -17, -6, -1, 19, 9, 5, 1, -7, -12, 5, -20, -7, 1, 8, 5, -1, 8, -7, 21, -10, -10, 4, 9, -10, -22, 11, -8, -14, 19, -15, 16, 4, 9, -18, -25, -3, 4, 11, 23, -12, 1, 5, 1, -14, -17, 1, 10, 1, 24, -2, 8, 9, 1, -17, -7, -1, -4, -4, 18, -9, 2, -1, -4, 9, -24, 5, -9, -2, -5, -3, -4, 10, 16, 8, -12, -6, -7, 0, 6, -14, 16, -10, 0, -5, 0, -17, 1, 19, 3, -22, 4, -16, 0, -9, -4, 9, -2, -5, 22, -18, -4, -8, -13, -20, -23, -8, -5, -19, 22, -4, -10, -9, -13, -14, -19, 14, 8, -19, 19, 1, -5, -12, 3, -1, -15, -6, -2, -31, 10, 8, -13, 9, 1, 1, -13, 8, -8, -25, -10, 19, -11, 7, -1, 1, 11, -2, 23, -2, -36, 19, 1, 9, 4, 21, 7, 1, 21, 28, -34, -16, -20, -7, -2, 27, 23, 8, 20, 31, -38, -32, -21, 16, 32, 33, 22, 11, 19, 20, -36, -27, -2, 26, 36, -4, -3, 13, 3, -19, -6, -31, 21, 36, 20, -13, -4, -5, -21, -18, 23, 13, 29, 10, -18, -24, 2, 8, -22, -14, 41, 27, 14, 3, -17, -15, 17, -5, -15, -16, 37, 13, 14, -7, -15, -5, 3, 3, -15, -11, 7, 23, 15, -1, 0, 5, 4, -11, -12, 0, -2, 12, 1, 10, 11, -1, -3, -9, 2, 4, -13, -9, -3, 1, 19, 8, -5, -3, 5, 25, -7, 11, -16, -2, 2, 19, -4, 1, -1, 19, 7, -8, -6, 5, 10, 2, 0, -3, 16, 9, 0, -1, -10, -3, 3, 13, 12, 12, -9, 6, -16, 3, 4, 12, 0, 14, -9, 3, -5, -9, -9, -6, 4, 12, -7, -2, 0, -10, 15, -15, 6, -7, -1, 1, -2, -7, -2, -9, 16, 32, -19, -24, -20, -17, 1, -4, -10, 10, 7, 29, -15, -11, -10, 0, 4, -10, -1, 10, -2, 32, -11, -27, 5, 9, 12, -17, 12, 11, -5, 5, -5, -13, 27, 15, 14, -32, 1, 19, -17, -33, 19, 7, 34, 18, -4, -18, 11, -5, 9, -20, 9, 10, 15, 6, -10, -8, 15, -1, 6, -13, 9, 19, 1, 0, -27, 2, 0, 3, -4, -2, -7, 22, -1, 9, -14, 13, 9, -12, -6, 11, 3, 16, 1, 6, -8, 7, -6, 6, 6, 21, 7, 19, -1, 15, -20, -1, -10, 5, 12, 0, -1, 17, -3, -5, -12, 13, -13, 1, -1, 12, -8, 1, -2, 10, 9, 9, -3, -1, -21, -13, -1, 15, -4, 22, 7, 16, 1, -17, -13, -17, 2, -8, 18, 25, 31, 10, -4, -21, 14, -5, 3, -7, 5, 0, -9, 10, -11, -18, 13, -4, 13, 1, -8, -41, 0, -2, -1, 0, 17, 18, 16, 14, -18, -38, 5, -6, -18, 10, 2, 10, 13, 9, -7, -32, -2, -27, -4, 13, 7, 13, -12, -5, -11, 3, 3, -29, 1, 8, -4, -5, -18, -9, 7, 7, -1, -23, -1, -12, 7, -6, 0, -16, 28, 16, -4, -19, -5, -7, -14, 14, -9, 7, 23, 8, -13, -16, 16, -11, 6, 22, -2, -13, 1, 18, -7, -2, 7, 11, 1, -4, -1, -23, -9, -1, 14, -13, 4, 5, -11, -15, -9, -5, -7, -2, -5, 12, -3, -2, -11, 4, 3, 5, 14, 0, 6, 0, 11, 8, -12, -14, 0, -1, 12, 3, 1, 21, 3, -5, 1, -22, 13, -10, 15, -13, 15, 9, 15, -16, -3, 1, 15, -2, 6, -27, 4, 7, 4, -10, 9, 16, 7, 16, 1, -37, -3, -9, -10, 7, 23, 17, 0, 21, 9, -17, -9, -32, -30, 18, 29, 8, -19, 37, 4, -24, 2, -49, -19, 16, 17, 1, -14, 6, 11, 16, 28, -25, -28, 4, -15, -7, -8, 9, -10, 44, 44, -16, -9, -2, -21, -26, 0, -2, -5, 42, 20, -1, 4, 6, -17, 2, 4, -26, 2, 28, 8, -8, 6, 10, -8, 22, 9, -36, -11, 2, 1, -2, 15, -6, -2, 21, 10, -38, 0, -6, -6, -1, 19, -17, -11, 6, 9, -19, 10, -13, -1, 9, 7, -10, 0, 16, 6, -12, 4, -11, 4, -12, 4, -7, 14, 17, 7, -21, -3, -30, -6, -18, 21, -9, 2, 11, 14, 1, -2, -38, -7, -2, 16, -10, 12, -3, -4, 9, 19, -11, 2, -9, 9, 5, -5, -10, -9, 18, 26, 8, 8, -4, -6, 10, 6, -31, -4, 9, 4, 17, 7, -8, -27, 17, 8, -19, 1, -4, 5, 23, 13, -14, -17, 4, -17, -3, 4, -14, -6, 13, 20, -4, -23, -14, -6, -4, 8, -9, 1, 6, 6, 7, -12, 12, -15, 8, 9, -7, -5, -6, 6, -11, -1, -7, -1, 2, 7, -3, -8, -4, 9, 7, 13, 4, 1, -2, 9, -8, 11, -11, 3, 6, -1, -8, -11, -11, 9, -6, -4, 3, -7, 6, 4, -5, -9, 5, 16, 13, -3, -4, -7, -17, 10, 16, -9, -20, -4, 22, 8, -8, 7, -8, -5, 11, -7, -3, -6, 9, -7, -14, -8, 12, 4, 3, -7, 11, -10, -21, 4, -5, 12, 11, 13, 3, 0, 7, -29, -19, 9, -7, 8, 17, 19, -7, 12, 8, -7, -5, -10, -6, 0, 20, 19, 9, 10, -1, -10, -6, -11, -18, -4, 11, 26, -18, -1, 10, -1, 1, -3, 5, -5, 21, 16, 3, -2, 9, 6, 0, 3, 10, 3, 5, 5, -15, 1, 2, 9, -5, -9, 2, -2, 12, -4, -20, -12, 5, -11, -14, 17, 26, 1, -9, 11, -4, -12, -4, -35, 1, 39, 32, 4, -5, 15, -3, -11, 19, -34, -17, 48, 23, -6, -11, 24, -5, 10, 26, -45, -6, 49, 18, -16, -4, 6, -7, 14, 16, -32, -1, 29, -19, -11, 2, -2, 9, 17, 18, -7, 9, 8, -36, 16, 8, -14, 4, 17, 9, -6, 24, -10, -23, 19, 3, -11, 16, 6, -7, 26, 12, -12, -2, 27, -1, -21, -1, 4, -1, 24, -1, -19, 17, 9, -16, -16, 5, -7, -10, 39, -15, -26, 18, 16, -8, -19, 9, -3, -9, 29, -6, -23, 17, -3, -6, -15, 15, 1, -3, 18, -10, -10, 4, 7, -5, -1, -12, 0, 0, 4, -13, -17, 10, 3, -13, -7, -5, 8, -10, -12, -8, 33, -18, -11, -11, 6, 6, 1, 5, -17, 5, 37, -25, -10, -20, 0, 4, 5, 5, -8, 15, 36, -26, -25, 1, -6, 7, 11, 21, -18, -8, 32, -28, -34, -34, -12, 12, 24, 15, -8, -5, 17, -33, -37, -21, 1, 11, 20, 15, -24, 19, 9, -20, -39, -24, 10, 2, 8, -6, -16, 12, -12, -8, -10, -20, 11, 16, -11, -8, -16, 13, -10, 23, 6, -23, -6, 6, -10, -8, 4, 8, -20, 30, 3, -17, 7, 0, -12, 21, 30, -5, -18, 17, -3, -19, 10, -15, -9, 9, 23, -11, 3, 17, 0, -14, -2, -1, -20, 11, 19, -6, 3, 12, 5, 4, -12, -11, -18, 13, 12, -14, 5, 25, -1, 2, -15, 3, 3, 3, -16, 5, -9, 7, 7, -12, -4, -3, 10, 9, -20, -5, -12, 1, 23, 25, -16, -3, 6, -3, -1, -13, -11, 18, 11, 15, -14, 6, 10, -7, -6, -9, -1, 20, 13, 4, 4, -18, -7, -5, 9, 5, -5, 0, -9, 9, 6, -12, -4, -1, 11, 1, -8, -19, 1, 4, 15, -12, -5, 2, 29, -9, 13, -19, 15, 14, 3, 11, -5, 2, 8, -1, 5, -17, 11, 14, 9, 1, 2, -5, -2, 1, 1, -9, 10, -4, -6, 5, 2, -4, 2, -13, -4, 3, 11, 8, 5, -4, -3, 1, 18, -8, -4, -2, 6, 2, -2, 2, 0, -11, 9, -5, 12, -1, -1, -3, 5, -7, 5, 6, 6, -6, -1, -14, -6, 14, 3, -3, 12, 9, -7, 8, -19, -2, 12, -5, 2, -9, 17, -10, -6, 10, -11, -10, 8, 3, -9, 14, 19, -10, -4, 0, -7, 21, -3, -19, -18, 15, 0, -16, 14, 7, 7, 19, 2, -9, 9, -9, -18, 3, 11, -4, 15, 22, -1, -3, 4, -9, -18, 1, 6, -11, 11, 7, -11, 6, 12, -2, -16, -3, 12, 8, 1, -5, -5, 7, 18, -8, 16, 1, 8, 12, -6, -21, 0, 25, 14, -9, 21, -7, -7, 27, -16, -30, 10, 9, 3, -1, 12, -44, 0, 29, 6, 13, 17, -23, -14, 11, -9, -37, 6, -8, 5, 58, 14, -30, -13, 14, -19, 10, 21, -34, 13, 43, 0, -10, 4, -2, -20, 53, 14, -45, -3, -5, -9, 7, 11, -5, 0, 52, 9, -27, -18, -57, -19, 26, 11, -18, -10, 33, 4, 0, -26, -32, -3, 2, 20, -11, 6, -2, -14, 6, -4, -22, 16, -5, -19, 4, 13, -17, -27, 14, -9, 2, 21, 1, -14, 19, 15, -4, -4, -17, -22, 5, 13, -2, -19, 17, 8, 6, 0, 4, 1, 4, -10, 3, -1, -1, 1, -7, -2, 10, 7, 8, -8, -2, 1, 2, -11, 0, 3, -3, 22, 14, 4, -15, 3, 2, -12, -8, -8, 11, 13, -8, 6, -7, -9, 7, -11, -23, 10, -4, 8, -2, -5, -7, -7, -10, -8, -4, 2, 12, -4, 9, 1, -8, 2, 9, -1, -1, -12, 7, -3, 7, -6, 5, -6, 8, -8, 6, -7, 4, -5, 13, -2, 3, -8, -4, -16, 9, 1, 2, 11, 6, 5, -12, 10, -1, -18, 1, 13, -1, 8, -2, 4, -2, 8, -11, 0, -3, 6, -10, 13, -4, 10, 13, 2, -8, 4, 5, 9, -1, 8, -15, 1, -3, 5, -16, 17, 2, 9, -5, 0, -12, 10, -2, 9, -5, 5, 4, 6, -5, 9, -22, 1, -10, 9, 5, 11, 2, -5, 0, 5, -12, 22, -4, -14, -3, 16, -5, -13, 9, -30, 3, 7, -34, -20, 16, 24, -25, -6, 28, -23, -11, 25, -45, -37, 13, 15, -34, -4, 47, -23, 0, 30, -33, -55, 23, -24, -37, 4, 25, -1, 13, 33, -30, -39, 5, -15, 2, 4, -8, -19, 16, 22, -22, -22, -11, -4, 21, 18, -50, -5, 11, -5, -16, 9, -11, -3, 22, 5, -25, 14, -1, -27, -11, 10, -10, -2, 2, 8, 10, 25, -16, -10, 9, 18, 2, -6, 3, 1, 11, 15, -4, -1, -1, 18, -7, -8, 10, -13, 20, 27, -8, 3, 7, 6, 8, 9, -11, -7, 18, 12, -7, 18, 7, 9, 3, -9, 1, -2, 6, -4, 8, -7, 4, -2, -5, -11, 2, 16, 6, -17, 4, -7, -1, -9, 2, 0, 15, 8, 2, -4, -5, 6, 5, 6, -6, 10, -8, 6, -5, 12, 16, -2, 8, 1, 4, -3, 1, 12, -6, 8, 3, -10, 8, 12, 8, -14, -2, -16, 7, 2, -1, 1, 0, 0, -7, 9, -7, -9, -3, 15, -7, 9, 9, -1, -9, -13, -5, -11, 9, 3, 3, 10, -3, 2, -11, -1, -4, 4, 14, 11, -14, -5, -6, -4, 4, 1, -5, 0, 14, 5, 4, 6, -3, 7, 12, -8, -9, -11, 16, 11, 3, 6, -1, -3, -17, -7, -16, -5, 16, 12, -13, 3, 7, 4, 5, 3, -19, -7, -10, 9, -2, 15, 0, 0, -14, -9, 15, -5, -8, 1, -6, 15, -1, -1, -1, -3, 23, -5, -9, -4, 15, 8, -7, 5, -13, 5, 3, -6, -5, -1, 20, 10, -4, 13, 0, -4, -6, -23, 2, -2, 22, 8, 6, 29, 2, 12, -18, -34, -9, 17, 38, -3, 21, 17, -3, 22, -22, -33, -7, 23, 35, -18, 9, 28, 11, 16, 5, -6, -21, 18, 36, -28, 5, 17, -5, 3, 9, -2, -11, 5, 2, -24, 23, 31, 15, -12, 47, 13, -15, -20, -28, -13, 12, 17, 6, -7, 58, 11, -38, -34, -24, -13, -10, 11, 8, 0, 44, 1, -34, -30, -25, 4, 0, 12, 2, 2, 20, 6, -20, -29, -35, 1, -2, 5, 11, -2, 6, 0, 16, 0, -12, 5, -13, 2, 4, 7, -20, -6, 16, 5, -20, 1, 5, -13, -11, 14, -15, -7, 12, 21, -4, 10, 5, 12, 5, 12, -23, -19, 33, 5, 3, 16, 5, -3, 0, 4, -9, -9, 17, 29, -19, 10, 9, 8, 3, -6, -10, -5, -2, 0, 24, 1, 9, 2, -9, 5, 1, 4, 4, -9, 18, 1, 17, -3, -2, -5, -7, 4, 11, 0, 1, -4, 6, -2, 6, 1, 17, -1, 15, 3, -1, -5, -4, -9, 6, -5, 21, 4, 4, 15, -8, -12, -4, -21, -3, -1, 9, -3, 18, 2, -3, 11, -24, -3, 3, -9, 15, -3, 15, 28, -12, 4, -18, -7, -14, 15, 0, -15, 33, 26, 7, 9, -11, -15, 3, 12, -12, -21, 30, 32, 9, -9, -18, -17, 6, 1, 7, -13, 16, -6, -7, -10, -8, -5, 7, 4, 39, -5, -30, -27, -16, -2, 31, 4, -3, 3, 13, -3, -16, -30, 20, 14, 7, -8, 11, -15, 11, 6, -9, -14, 30, 14, -29, -5, 13, -11, -19, 21, 16, -51, 27, 33, -21, 1, -8, 7, -14, 19, 19, -33, -4, 27, -7, -2, 2, -2, -9, 4, 4, -43, -14, 24, 5, 12, 10, 9, 12, -13, 14, -24, -12, -14, 25, 26, -14, 5, 4, -18, 2, 13, -18, -19, 10, 8, -7, -3, -3, -4, 17, 27, -23, -23, 3, 30, 9, 22, 3, -23, 11, 39, -19, -35, 3, 14, -9, 9, -9, -12, 14, 35, -15, -8, 4, 5, -3, 7, -8, -6, 11, 19, -11, 4, -5, 17, 1, -19, 1, -1, 0, 14, 0, -5, 8, -15, 12, -4, -17, 7, -1, 14, -2, 6, 0, -19, -11, 3, -6, -9, -1, 2, 15, 3, 11, 2, 3, 17, -23, -20, 12, 3, -2, -14, -2, 12, 17, 21, 11, -28, 16, 1, 3, 0, 2, -3, 4, 16, 0, 1, -4, -8, -5, 6, 17, 10, 8, 12, 5, 17, 10, -21, -19, 1, 9, 10, -6, -1, -6, 30, 3, -14, -5, 3, 9, 14, -9, -4, 10, 39, -15, -6, -9, 3, 11, 2, -9, -18, -5, 25, 2, 15, 0, 3, 1, 26, -17, 9, -9, -9, -11, 36, 9, 0, -17, 25, 0, -11, 5, -22, 6, 51, 23, -15, -16, 21, -17, -3, 3, -39, -14, 52, 13, -14, -14, 17, 7, -2, 16, -40, -14, 53, 4, 3, -16, -13, 11, -1, 22, -16, -15, 24, -19, -11, 5, -27, 15, 0, 32, -10, -17, 1, -26, 0, 4, -13, -8, -7, -1, 14, -18, -7, -14, -1, 2, 1, 5, -9, -23, 32, -14, -2, -18, 1, -9, 3, 0, -9, -11, 25, -5, -20, -15, 6, 9, -17, 4, 10, -11, 14, -18, -10, -6, 8, 1, -18, -5, -5, 5, 2, -11, -15, 10, -9, 6, -4, -5, 10, -13, 13, 6, 10, -1, 1, 2, -8, 2, -7, 2, 6, 23, 21, 0, 2, -6, -2, 3, 3, -2, 4, -4, 13, 14, 9, 7, -9, -6, -16, -15, 9, 20, 1, -8, -3, -14, -10, 8, -5, -5, -9, 6, 15, 6, 5, 1, -2, 5, -10, -7, -1, 8, -4, 10, 4, -6, -4, -9, 2, 2, -6, 0, 13, -15, -3, -11, -6, 1, -6, -9, 1, 11, -3, -4, 5, 18, 17, 8, 5, 0, 10, 6, 3, 1, 2, 15, 15, 8, -14, -13, 16, -17, 5, 11, -1, 18, 10, 2, -6, -8, 22, -6, 19, 8, -11, 14, 7, 10, -14, -17, 32, -2, -1, -11, -11, 13, 5, -8, 1, 1, 41, -2, -5, -11, 2, 7, 6, -10, -9, 17, 20, 1, -13, -27, -3, 16, -4, 0, -11, 16, 7, 5, 6, -19, -1, 7, 6, -4, 3, 5, -2, 21, 9, -2, 11, 0, -1, -5, -4, -2, -17, 14, 6, 1, 19, 12, -2, 0, -4, -11, 2, 3, 3, -3, 9, 8, -2, -6, 2, 7, 15, 1, 4, -28, 8, -4, 12, 8, -4, 23, 38, -9, -18, -19, -18, -1, 0, -4, -14, 41, 21, -27, -5, -42, -25, -1, -10, 9, 2, 34, 23, -36, 10, -37, -17, 4, 15, 3, -1, 28, 15, -34, 8, -39, -14, 4, 20, 5, 0, 3, 2, -26, -15, -9, -12, -5, 18, -5, -1, 3, 17, -13, 7, -11, 1, -7, 2, -4, -5, -1, 5, 9, 11, -5, -12, 13, -7, 2, -8, -15, 4, 10, -2, 8, -5, 2, 10, -2, -10, 6, 14, -3, 1, 1, -15, 14, 16, 6, -13, 11, -2, 11, 14, -3, -3, 19, 11, -5, 1, 11, 7, 9, 7, -4, -2, 3, 8, -9, -7, 2, 8, 18, -3, 5, 0, 15, 18, 0, -14, 11, 11, 26, 4, 6, 8, 7, 4, 16, 3, -6, -7, 3, 8, -4, -2, -6, -8, 5, 15, -1, -17, -6, 6, -10, 17, -11, -15, 5, 8, 3, -13, 8, -4, -7, -5, -8, -2, -10, 5, -2, 0, 4, 7, -6, -1, -11, 6, -7, -3, -2, 12, 13, 11, 0, 1, 5, 12, -5, -3, -7, -5, 11, -9, 0, -4, -19, -10, 6, 25, -17, 8, -1, -7, -6, 0, -8, 1, -9, 18, -7, 10, 17, -12, -3, 2, 2, -2, 1, 10, -17, 10, 21, 2, -25, 1, 12, 0, 3, -2, 7, 2, 0, -10, -17, -13, 9, 4, -13, 5, 12, 9, -5, -18, -12, -17, 10, -9, -20, -11, 16, 22, 25, 3, 13, -20, 5, 9, -23, -37, 23, 6, 2, 11, 23, 9, 17, -6, 5, -2, 7, 0, -3, 9, 22, 7, 2, -12, 21, 0, 9, -16, -27, -7, 17, 2, -10, -15, 17, -5, 3, 0, -20, 0, 33, 5, -22, -19, 4, -2, -6, -4, -1, -9, 39, -2, -1, -12, -12, -18, -1, 14, 20, -2, 25, -4, -18, 10, 9, 5, -12, 0, 29, 4, -4, 6, -4, -4, 15, 12, -9, -8, 19, 2, 1, 2, 4, -5, -2, 0, -18, -3, 17, -6, -13, 3, 15, -9, 1, -5, -7, 13, 1, -4, -4, 14, -9, 0, -4, -11, 8, 13, -10, -5, 6, 13, -7, -14, 8, -4, -2, 16, -7, -11, 7, 1, 4, 12, -6, -8, 1, 8, -21, 3, 12, -8, 7, 3, 2, 17, 12, -6, 1, 11, 4, -13, -14, -4, -2, 17, 15, -13, 7, 4, -5, 5, 5, 8, -7, 6, 4, -12, 2, 0, -7, -16, 0, 9, -10, 4, 5, 2, 24, 4, -7, 8, -8, 0, 8, -10, -20, 12, 29, -14, 18, -7, -2, 3, 10, 11, -20, -3, 21, -1, 13, 11, -16, -7, 6, -10, 3, 22, 0, -26, 24, 6, -10, -21, -8, -18, 3, 23, -14, -8, -2, -4, 0, 4, 3, -18, -5, 9, -10, -15, 11, -18, -6, 11, -1, -12, -6, 16, -6, -13, 24, -22, 3, 17, -13, -9, -37, -2, 19, 9, 30, 3, -2, -4, 9, -22, -44, -6, -7, -10, 16, 15, -2, -5, 23, 7, -15, -24, -47, -13, -18, 17, 1, -18, 6, -3, 4, -14, -36, -4, -5, 25, 10, -30, 1, 3, 29, -19, -21, -3, -25, 23, -1, -12, -16, 6, 10, -13, 10, 5, -14, 22, -6, -8, -8, 5, 4, 9, 13, -2, 0, 4, 14, -8, -5, -2, -9, -9, 8, 19, -1, -5, 9, 3, -10, -9, -14, -3, 11, 22, 2, -16, 16, 7, 8, 9, 0, 0, -1, 11, -2, -3, 1, 2, -5, 13, 3, -6, -3, -2, -8, -17, 9, 14, 0, -10, 0, 9, 11, 7, -11, -6, 12, -6, 8, 6, 2, 2, 0, 5, -15, -11, 3, 0, -4, 0, 7, 1, 6, -8, 0, -4, 0, 2, -2, 4, -3, 12, -13, 7, 2, -8, -3, 10, -9, 0, -8, 16, -8, 12, 1, 17, -1, 10, -6, 3, 10, -8, -11, 7, -12, 11, -1, 12, 9, -11, -2, 10, -5, 6, -14, -5, 6, 10, -11, -2, 9, -4, 22, 5, -15, -8, -3, 4, 4, 8, 14, 5, 6, 18, -1, 3, -13, 5, 8, -9, 6, 10, -9, 11, 8, 6, -2, -3, 1, -12, -10, 15, 18, 23, 2, 6, -11, 10, 6, -17, 4, 27, 31, 1, -14, 10, 7, -7, 5, -21, 3, 18, 28, 6, -24, 1, 8, 9, -6, -7, 3, 13, 27, 2, -16, -12, 23, 12, -7, -6, 15, 2, 15, 15, -16, 2, 21, 7, -15, -12, -8, 17, 25, 6, 2, 6, 15, 6, 3, 5, -5, 8, 15, 4, -5, 13, 17, 6, -10, 10, -3, 4, 19, 13, -23, 0, -6, 24, -3, -13, 13, 15, 12, -3, -11, -5, 10, 6, -16, 2, -13, 25, 0, 2, -8, 4, -10, 14, -6, -15, -13, 28, 17, 9, 0, 2, -15, 13, 6, -9, -12, -1, 47, 18, -10, 1, -16, 22, 9, 9, -28, 6, 39, 2, -17, -2, -5, 6, 9, 5, -26, 13, 33, -4, -10, 4, -5, 4, 8, 0, -12, -7, 20, -9, 7, 1, 1, 24, 1, -4, -12, 18, -6, 1, -7, 18, 5, 18, 4, -1, 6, 5, -9, -6, -6, 13, 10, 8, 8, 5, 13, 19, -17, -5, 5, 4, 7, 9, 13, 15, 15, 3, -24, 6, 7, -1, -5, 13, 2, 8, 3, 3, -2, 11, 4, -2, 4, 7, -1, -5, 1, 9, -4, 9, 2, -9, -2, 0, -3, -6, -16, -10, 22, -1, -9, 0, -13, 5, 14, -2, -10, 1, 15, -10, -4, 7, -12, -7, -6, -7, -11, 8, 2, -3, 0, 15, -25, -7, 3, -3, 5, 5, -3, 1, 18, 12, -16, -4, -9, -8, -12, 7, -9, -8, 32, 25, -11, 0, -8, -6, -10, -2, 7, 10, 17, 24, -8, -3, 2, -10, 1, -18, 22, 17, 3, 4, 1, -8, 6, 20, -9, -12, 21, 29, -23, -4, 11, 3, 0, 30, 4, -18, 15, 5, -31, -9, 2, -6, -11, 31, 35, 0, -1, -8, -17, -19, -17, -10, 2, 16, 26, 15, -4, 15, -11, 1, -36, 10, 1, -4, -15, -4, -3, 26, 25, 16, -27, -17, 22, -4, -20, -8, 14, 28, 26, 3, -9, -18, 9, -17, -8, -21, 18, 10, 9, 16, 5, 0, -6, -12, -5, -27, -10, 17, -18, 1, 26, 9, -16, -12, 5, -18, -9, 6, -29, 11, 31, 5, 6, -22, 19, -12, -24, -1, -12, 16, 27, 7, 1, -22, 13, 20, -9, -18, -1, 16, 14, 20, 1, -7, -3, 18, -19, -1, 10, 3, 9, -4, -5, -2, -8, 22, -16, 0, 7, 5, 5, -6, 0, 12, -16, 4, 16, 1, -10, -3, -3, -6, 9, 4, -3, -8, 5, 8, 5, 8, -13, 8, -11, 11, -7, 15, 0, -1, -17, 6, -6, -6, 5, 15, 4, -7, -1, -7, -29, -2, -7, -23, 6, 18, 0, -23, -4, 11, -27, 3, -8, -22, 10, 21, 4, -26, -8, 4, -1, 8, 5, -4, 14, 17, 0, -33, -19, 6, -1, 19, -6, -10, 9, 9, 22, -12, -16, 9, 21, 4, 1, 19, -3, -6, 0, 7, 4, 11, 34, 1, -10, 2, -14, -28, -5, -8, -1, -4, 31, -8, 6, 8, -6, -22, 19, -6, 0, 7, 22, 1, -12, 7, -11, -24, 7, -10, 11, -9, 20, 4, 12, -6, 2, -17, 4, -8, 3, -9, 15, 10, 17, 5, -4, 5, -11, -4, 8, -14, -3, 20, -3, -9, 3, -12, -25, -12, 12, 2, 1, -6, 13, 8, 8, -13, -1, 5, -26, 17, 7, -13, -12, 5, -2, 6, -13, -8, -3, 6, 13, -1, 2, 18, -15, -5, 0, 14, -12, 13, 17, 9, -5, 11, -15, -14, -1, 24, -4, 11, 1, 8, 12, 3, -14, 10, 3, 25, 7, 14, -7, 2, 6, 7, 11, 8, 1, 3, 12, 6, -10, -18, -4, 1, -7, 31, -5, 13, 13, -11, -9, -5, -15, 0, 0, 5, 0, 7, 10, 13, 2, 2, -7, -10, 2, 16, 8, 12, 2, 0, 0, 2, -2, 2, -3, 13, 0, 0, -2, -5, 17, -5, -4, -9, 13, -4, 1, -8, 6, 0, 21, 0, -19, -8, 7, 2, -14, -13, 8, -2, 9, -19, -14, 4, 9, -12, -10, -13, 20, 2, 13, -12, -1, 1, 1, 5, 41, 23, -36, 0, -7, -4, 7, -2, -3, 14, 23, 16, -24, -17, 2, 2, -1, 2, -1, -14, 25, 0, -29, -10, 16, 12, -8, 1, 0, -13, 17, 5, -19, 5, 15, 21, -8, -7, 2, 12, -20, -25, 12, 4, 8, 29, -4, 0, 13, 4, -27, -37, 8, 17, 23, 25, -16, -20, 8, 18, -21, -32, 18, 16, 26, 12, -17, -6, 0, 9, -28, -8, 10, 24, 7, -13, -15, -14, 8, -13, -20, 6, 33, 21, -10, -21, -1, 2, -1, -9, -24, 21, 32, 23, -37, -41, -2, 6, 0, -16, -14, 24, 31, -6, -18, -23, -9, -2, 3, -21, -24, 34, 39, -10, -31, -23, 9, -7, 3, -10, -19, 20, 30, -8, -35, -1, -2, 6, 0, -2, -15, 25, 18, -19, -27, 15, 0, -5, 11, -13, -7, 27, 21, -23, -3, 24, 11, 2, -8, -18, 15, 19, 0, -14, 11, 0, 0, 4, -16, -4, 17, 11, -5, -6, 6, -10, 11, 8, -13, 12, 12, 5, -14, -1, -3, 2, 0, 8, -16, 11, 16, 0, -7, -4, 0, 0, 7, 1, -9, 4, -9, 1, 10, 11, -14, 17, -19, 1, 7, 9, 2, -3, -4, 9, 4, 17, -19, 6, 10, -2, 5, -12, 17, 9, -3, -2, -2, -3, 7, 5, -3, -15, 3, 19, -5, 8, -8, -16, 8, 0, -18, -2, 10, 17, 17, -8, -9, 12, -11, -1, -1, -4, -4, 18, 12, 5, -13, -8, 7, 18, 3, 4, -5, -2, -16, 0, -10, -7, -2, 0, 3, -5, 0, -21, -8, 6, -10, -5, -7, 13, -2, -3, 1, -18, -1, 12, -9, -2, 1, -1, 13, 6, -14, -21, 12, 18, 0, 2, 18, 10, -8, 12, -19, -16, 16, 13, -9, 10, 3, -4, -33, 3, 18, -1, 15, 19, -9, -2, 0, -7, -32, -2, 26, 9, 10, 10, -9, -1, -15, -7, -15, 1, 16, -2, -1, -10, -6, 0, 5, 8, 31, 8, -10, 4, -23, -21, -4, -11, -11, -2, 59, 5, -41, 3, -41, -27, -11, -13, 9, -1, 57, -2, -45, 6, -19, -25, -31, -4, 0, -19, 13, 2, -44, -1, 18, -21, -37, 8, 16, -9, -17, -4, -12, 17, 33, -4, -45, 1, 11, 0, -31, 5, 30, 8, 27, 6, -33, 4, -9, 16, -29, -16, 38, -9, 24, 27, -5, -2, -4, 10, -7, -4, 30, -17, 32, 22, 2, 5, -8, -11, -7, -1, 10, -9, 30, 10, 23, -7, -6, -6, 18, -6, 5, -11, 17, -7, 8, 7, 2, 2, 19, 3, -6, -14, 5, -12, 12, -10, 13, 9, 6, 4, 7, -1, 3, 8, -2, -2, -8, -3, -1, 1, 3, -8, 4, 4, 1, 9, -12, -2, -8, 5, 5, 5, -11, 0, 14, -1, -2, -1, 4, 12, -2, 14, -18, -6, 13, 0, -4, 4, -12, -4, -2, 0, -10, -3, 10, 0, 6, -13, 12, 15, -15, 6, -12, 5, 5, 5, 0, -12, 8, -4, 7, 3, 1, 1, 4, -1, -3, 1, 9, -3, -11, 15, -3, -3, -9, 10, 15, 1, -5, 14, -6, 12, 3, 10, 8, 11, 2, 5, -3, 10, -1, 14, 6, -1, 0, 14, -3, 1, -38, 11, 4, 12, 17, -7, -1, 9, -4, 3, -25, 4, -10, 14, 15, -1, -18, 7, -11, 15, 19, 1, 8, -11, -32, -24, -4, -3, -6, 22, 40, 11, 13, -31, -59, -8, -17, -12, 11, 11, 40, -6, -7, -25, -48, -7, -19, -15, 13, 5, 4, -10, -14, -3, -15, 30, -11, -8, 14, -7, -39, -32, 5, 11, 40, 29, -28, -14, 13, -4, -45, -4, 11, 27, 41, 2, -26, -13, -22, 0, -13, -1, 3, 9, 14, -14, -4, 20, -20, -7, 0, -1, 16, 9, -11, -9, -3, 22, -10, -16, 7, 4, 18, 15, 2, -11, 16, 6, -9, -7, 16, -2, -10, 12, -17, 1, 6, 10, 7, -13, 12, 11, -27, -6, -19, 6, -2, 22, 7, 10, 20, 5, -23, -14, -16, 8, 12, 14, -9, 6, 0, 3, -15, -14, -18, -5, 9, 19, 1, 9, -2, 4, -17, -23, -11, -6, 1, 4, 6, 16, 3, -2, -6, -8, 9, -4, -5, 10, -2, 6, 3, -3, -3, -2, 9, -3, 3, 2, 8, -14, 4, 2, -15, 3, 18, 6, 2, -17, 9, -9, 2, 0, -3, -10, 17, -4, -11, -6, -7, -15, 17, 2, -11, -2, 19, -8, 5, -20, 9, 6, 5, -8, 7, 16, 17, -9, 9, 9, -4, -4, -8, -13, 7, 25, -11, 3, 11, 5, -3, 11, -2, -4, 20, 8, -7, 9, 19, 15, -14, 10, 8, -26, -5, 14, 14, 2, 16, 5, 3, -8, 18, -20, 0, 14, 7, 22, 15, 8, 17, 2, 7, -28, -9, 23, 8, -4, -1, 0, 5, -2, -21, -21, 14, 11, -20, -14, 2, 5, -6, 15, -23, -11, 38, -16, -9, -2, 2, 9, 6, 3, -10, 5, 32, -25, -30, 4, 17, -2, -3, -16, -17, 16, 25, -26, -19, 6, 7, -4, -6, -3, 7, 13, 4, -27, -18, 11, -19, -14, 2, -10, 6, 6, -11, -11, -17, -4, -37, -21, 6, -7, 10, 21, 0, 5, -15, -19, -39, -10, 0, -10, -1, 11, -15, 6, 3, -24, -42, 0, -2, -15, 9, 3, 11, 0, 8, -28, -39, 22, -9, -8, -20, 2, 1, 6, 22, -22, -12, 4, 4, -1, 3, -2, -2, -2, 23, 19, -13, -1, -2, -6, -13, -2, 0, -21, 16, 22, 7, 2, -3, -1, 10, -25, -7, -10, 11, 27, -5, -3, 6, 6, 9, -14, -5, -19, 15, 4, 0, 2, 13, 14, 0, -8, -10, -11, -9, 4, 2, 5, -5, -3, -13, -3, 6, -3, 0, -4, 3, -6, -8, -9, -13, -4, 7, 3, 13, 4, 0, -1, 0, -4, 1, 5, -9, 12, -12, 11, 0, 3, -6, -6, -7, 18, -9, -13, -3, -6, 13, -2, 13, -12, -4, -3, -7, 10, 20, 2, 8, -3, 5, -17, 14, 3, -11, 3, -6, 0, 6, -12, 14, -17, 14, -3, -3, 4, 12, -5, 16, 4, -12, -12, -3, 4, -15, -14, 9, -7, -1, 9, -9, 4, 16, 18, 1, -15, -19, -9, -17, -12, 0, 14, 8, 33, -8, -10, -8, -12, -38, -12, 14, -3, 6, 21, 8, -12, 0, 6, -20, -12, 11, 1, -23, 11, 3, 10, 3, 16, -16, -3, -12, -3, -12, -21, -3, 11, 12, 2, 6, -9, 9, -6, -3, -19, -9, 24, -6, 3, 21, 2, -16, 13, -1, -28, -27, 5, -3, 3, 8, 16, -4, 10, -5, -18, -25, 1, -11, 3, 12, 22, -17, -5, 13, -9, -17, 8, 6, -4, 4, 23, -17, -10, 7, 11, -5, 10, 22, -6, 11, 5, 8, 4, -12, -16, 14, 32, 4, -15, 15, 10, -11, 9, -3, 3, 21, 24, -7, -8, 16, 6, -17, 12, -21, -1, 22, 20, 8, -19, 3, 3, 4, -7, -28, 2, 28, 2, -8, 1, -14, -22, 14, 1, 10, -8, 13, -5, -1, 12, -14, -26, 20, -3, -1, 4, 9, -28, 5, 13, -25, -25, -3, -4, 10, 9, 12, -24, -15, 22, -4, -25, 5, -5, 10, -10, 11, -4, -26, -2, 16, -14, 0, 20, -8, 5, 14, -14, -18, -2, 1, -19, 1, 18, -6, -7, 5, -13, -14, -9, 11, -16, 6, 9, -10, -2, -2, 4, -10, 6, -3, 5, 12, 13, -9, 16, -11, 1, 14, 0, 12, 1, -4, -5, -11, 9, -3, 1, 6, 16, 17, 20, 3, 4, -16, 11, 13, 6, 0, 17, 6, -5, -16, 19, 2, 6, 2, 11, -3, 19, -10, 17, -15, 15, 2, 10, 17, 9, -4, 2, 5, -5, 2, -15, 30, 18, 12, 18, -24, -14, 5, 8, -16, -3, 24, 13, 20, 29, -39, -34, 13, 7, 13, -1, -4, 9, 6, 11, -29, -31, 5, 1, 11, 12, -6, -17, 9, 16, 0, -20, 24, -6, 17, 21, -8, -24, -2, -5, -4, -7, 1, 7, -2, 8, 9, -1, -28, -7, -9, -27, 17, 6, -2, 9, 16, -15, -21, -6, -15, -14, 20, 23, 14, -8, 15, -18, -17, -28, -10, -21, 3, 28, -6, 2, -14, -8, -1, -5, 32, 18, 4, 20, 13, -18, -27, -19, -8, -10, 50, 1, -17, 6, 1, -8, -27, -5, 20, -18, 52, 15, -7, -8, -15, -6, 15, 2, 21, -12, 26, 5, 1, -8, -12, -20, 7, -8, 6, -24, 6, 3, 1, -2, -4, -11, 5, -12, 23, -8, -13, -1, -7, -9, -10, -10, 7, 3, 12, -15, -8, -9, -8, -4, -1, 6, -14, -15, 23, -16, -8, -14, -3, -1, 12, 4, 6, 4, 3, 8, 2, 1, -4, 0, -3, -3, -5, 11, -1, -11, 4, -6, 0, 6, -3, 3, -5, 19, 1, -7, -9, 3, 9, 14, 12, -5, -10, 8, -4, 1, 8, -1, -4, 10, 8, -11, 5, -4, -3, 3, 7, -11, 22, 7, -7, 3, 12, -17, 0, -5, 12, -4, -3, 14, 8, 12, 21, 13, -17, -18, 7, -11, 6, 23, 0, -6, 24, -7, -30, -15, -7, -4, -11, 2, 5, 17, 28, 9, -45, -20, -9, -4, -40, -15, 5, 11, 9, 25, -36, -9, -9, -9, -46, -44, 17, -5, 3, 28, -24, 0, 4, 6, -48, -30, 8, -4, -15, -11, -1, -2, 1, 16, -36, -31, 10, -5, -40, -7, 47, 3, -2, 13, -8, -27, -16, 18, -29, -43, 25, 11, -7, 7, 12, -18, -16, 18, 1, -30, 1, 0, -7, 9, 38, -1, -11, 6, 6, -11, -10, 8, 9, -1, 23, 13, 0, -8, 23, 8, 0, -11, 19, 7, 6, 3, -3, -3, 4, 8, -14, -1, 18, 18, 26, 2, -6, -6, -9, 1, 12, -11, 1, 5, 10, 4, -9, -9, 0, 12, 7, 4, 6, -1, 10, -5, -9, -2, -15, -4, 6, 7, 5, -5, 0, -3, -6, -15, -1, 22, 0, -6, 3, -5, 16, 5, -5, 0, -5, 16, 7, 4, -6, -11, -6, 16, 9, -1, 10, -2, 3, 5, -4, 0, 3, 22, -12, -11, 14, -3, -7, -7, -4, 1, 1, 17, -7, 4, 13, 10, -3, -10, 12, -3, 2, 13, 17, -7, -7, 7, -1, 4, 9, 18, 4, 3, 15, -4, 1, 13, 6, 6, 2, 7, -10, 8, -2, -1, -16, -4, 14, 15, 22, -13, -1, -9, -2, 18, 3, 2, -9, -17, -9, 6, 13, 22, -10, 9, 0, -4, -8, -19, -8, 6, 4, 17, 7, 6, 9, -7, -8, -25, 2, 20, 18, 11, 5, -1, 14, -5, -8, -11, 8, 14, 7, 14, -5, 13, -24, 10, -3, -11, -7, 15, 15, 11, -6, 3, -32, 7, 0, 2, 20, -4, -12, 17, 6, -6, -31, 31, -1, 16, 12, 0, -22, 12, 14, -18, -22, 35, -8, 11, 25, 12, -12, 16, -9, -3, -3, 29, -29, 11, 17, 12, 7, 9, -9, -25, 24, 23, -24, -6, -4, -1, -2, 18, 3, -8, 18, 30, -20, 11, 2, 2, 8, 19, 6, -22, 34, 17, -13, -11, 4, 11, 8, 12, -10, -13, 21, 7, 11, 0, 6, -4, 3, 4, 9, -21, 22, 9, -3, 4, 1, -2, 2, 15, -14, -15, 34, 8, -4, 9, -8, -5, -2, 24, -3, -14, 42, 16, -6, -13, -18, 2, 16, 6, -3, -21, 41, 26, -17, -10, -12, 9, 12, 23, 2, -4, 19, 27, -23, 9, -14, -1, 7, 21, -6, -7, 6, 9, -12, 10, -12, 2, 6, 23, 3, -9, 13, 11, 26, -3, -4, 3, 1, 9, 13, 4, -15, 4, 12, -6, 1, 11, 11, 7, 2, 12, -1, 3, 11, -19, -12, 5, -3, -7, -12, 4, -9, 8, 2, 1, -5, 7, 12, -8, 8, 3, -8, 12, -13, -14, 3, 3, 4, 9, 12, 13, 4, 9, 4, -21, -7, -3, -4, 4, 2, 3, 9, 1, 18, 8, -13, 6, -2, 12, -2, 0, 3, 4, 2, -7, -2, -8, 15, -2, 7, -13, 17, -2, -1, -1, -3, -16, 17, 24, 0, -9, 25, 7, -34, -10, -8, -13, 3, 9, 6, -5, 21, 12, -23, -29, -5, -17, 22, 29, 3, -14, 26, 24, -36, -25, -6, 11, 8, 16, 7, 8, 7, 23, -47, -33, -3, 7, 15, 23, 1, -14, 0, 7, -22, -5, 6, -16, 13, 25, 5, -14, -4, 9, -23, -7, 0, -15, 14, 8, 10, 11, -3, 20, -11, -27, 17, -18, 16, 19, -8, -4, 2, 10, 1, -30, 13, -12, 14, 5, 10, -13, 18, 22, -6, -23, 15, -9, 24, 5, -10, -14, 16, 11, -31, -18, 25, 12, 25, 13, 8, -15, 11, 29, -22, -34, 41, 27, 7, -7, 10, -15, -4, 18, -8, -15, 29, 14, 9, -12, 2, 2, -12, 13, 1, 6, 15, -6, 1, -5, 6, -3, 9, -7, 21, -4, -1, -5, 5, -15, 2, -9, -7, -8, 27, 3, 0, 1, -6, -9, -12, -8, 6, 7, 20, 6, -9, 1, 8, 6, -6, 8, 1, 10, 17, -7, -2, -4, 7, -5, -15, 8, 6, 2, 8, 7, -9, 16, -2, 0, -10, 11, -9, 17, 4, 5, -15, 5, 8, -6, -3, 0, 6, 10, 17, 4, -3, -8, 12, 7, -9, 14, 1, 8, 7, 1, -13, 3, -2, 10, -3, 11, -9, 14, -1, 0, -4, 15, -2, 19, 0, 5, 9, 3, -4, -2, 5, -3, -2, 0, -12, -18, 12, -4, 8, -8, -12, -12, 7, -12, -2, 4, 14, 11, -2, -15, -17, 10, 2, -5, 1, 3, 23, -17, 2, -14, -10, 1, 1, 4, 13, 15, -8, -15, -2, -13, -16, 1, 13, -1, 5, 30, -3, -1, -10, -9, -14, 15, 3, 4, -5, 20, -20, -9, -9, 1, 20, 7, 2, -11, -5, 8, -27, 5, 3, 22, 18, -5, -14, -10, 18, 0, -7, 16, 12, 24, 2, -3, -9, 1, 14, -9, -6, 2, 7, 6, -21, 1, 4, 1, -10, -21, 4, 10, -10, 11, -28, 5, 12, 11, -13, -32, -7, -10, 20, 16, -11, 5, 27, 0, -2, -6, -25, -27, 18, 24, -2, -8, 12, -2, 18, 5, -28, -39, 14, 11, 12, 2, 4, -21, 0, -1, -30, -11, -10, -7, 22, 26, -13, -11, 13, -10, -3, 5, -39, -26, 33, 15, 1, -17, 1, -11, 0, 9, -27, -22, 8, 8, -2, -5, -9, 5, 10, 12, -9, -17, -12, 9, 8, -6, -9, -5, 18, -1, -2, 2, -21, -15, 7, 3, 2, 3, 14, -11, -6, -13, -22, 4, -6, 16, -9, 1, 14, -3, -4, -5, -20, -11, 5, 15, -2, 11, 11, 5, -16, 11, 7, 1, -3, 6, -10, -1, 13, 3, 2, -14, 13, -10, 7, -6, 12, 4, 1, -2, 1, 8, -2, 5, 7, -6, -8, -4, 9, -9, 6, -7, 4, -6, -12, 1, -5, 11, -10, -7, 4, 3, 2, -2, 5, -10, -6, 7, -13, -14, 15, -5, 0, -13, -5, 1, -7, -16, 12, -11, 19, 8, -2, -7, 5, -9, -6, -17, 20, -2, 8, -2, 24, -17, 14, -14, -2, -21, 16, 2, 8, -18, 22, -22, 9, 3, 11, -16, 17, -10, 5, -16, -9, -4, 22, -8, 5, -10, 5, -15, 17, -7, -5, 1, 32, 7, 5, -14, 17, -13, 12, -9, 5, -16, 19, 24, -10, 0, 17, 4, -15, -13, -9, -1, 25, 21, -9, 17, 19, 7, -11, -22, -10, 12, 12, 22, 16, 28, 8, -4, -2, -11, -12, 26, 27, 16, 2, 21, -41, -13, 17, -1, -2, 20, 29, -7, -4, 33, -55, 12, 25, 6, 17, 1, 7, -6, 10, 8, -31, 23, -11, 5, 33, 13, 3, -12, 2, -6, -9, 28, -34, 8, 10, 10, -10, -8, -1, -10, 17, 18, -47, -4, -8, 8, -10, -4, -9, -4, 34, 0, -43, 0, -30, -11, 4, -1, -1, -8, 21, -3, -23, 2, -29, -4, 6, -1, -14, -3, 6, 4, -12, 6, -13, -9, -24, 1, -9, -5, -8, 18, 1, 10, 14, -12, -25, -5, 0, -6, -5, 24, 10, -10, 0, -2, -4, -9, 15, 5, -6, 25, 13, -19, 13, 2, -16, 0, 5, 7, -13, -7, 23, -2, 2, 2, -10, -4, 0, -4, -13, 1, 6, -24, -7, 1, -4, -10, 13, 3, -3, -13, -5, 0, -13, 7, -7, -5, -6, -1, -1, -7, -1, 8, 0, 8, -1, -4, 10, -16, -20, 0, 0, 7, -12, 13, -18, -1, 16, -13, -23, -22, 16, 27, -7, 20, -24, -9, 14, -1, -7, 1, -12, 29, -2, 7, -17, 2, -10, 6, 2, -7, -2, 20, -2, 9, -6, 2, -15, -17, 6, -12, -5, 26, 16, 5, 7, 8, -10, 0, -2, 6, 10, 27, 16, 1, 0, 6, -16, -15, -3, -9, 7, 21, 8, -8, 18, -2, 4, 2, 7, -13, -1, 27, -12, 5, 34, 2, 4, 10, 1, 10, -5, -3, 0, -2, 16, -8, 6, -2, 12, 8, -13, -10, -2, -19, 13, 3, -9, -4, 10, 11, -20, -18, -3, -22, 16, 16, -5, -11, 12, 7, -8, -18, -8, -31, 2, 9, -9, 1, -5, 21, 11, -30, -25, 2, 7, 11, 18, 10, 2, 8, 6, -60, -16, 9, 1, 1, 14, 9, -4, -18, -23, -41, -17, 39, 1, -8, 19, 10, 6, -20, -8, -6, 17, 32, 9, -17, -6, 8, -4, -15, -9, 1, 29, 31, -6, -1, -4, -8, -4, 8, -2, 22, 13, 8, -15, -10, -13, -5, -12, 14, 24, 34, 22, -8, -3, 18, -13, 1, -12, 16, 25, 12, 9, 9, -21, 0, -3, -7, -8, 18, 18, 10, -5, -3, 13, -6, 3, 15, 0, 9, 19, 8, -15, 2, -2, -8, 2, 2, -10, 18, -5, -14, -14, -8, -7, -7, 9, 4, 3, 16, 0, -16, -11, -2, -2, -4, -7, 10, 4, -4, 3, 11, -5, 5, -9, -2, 12, -11, 9, -1, 1, -1, 11, 12, 3, 2, -9, -5, -8, -15, -3, 4, -6, -5, 2, -6, 0, 0, -8, -7, 2, -7, 9, 5, -1, 6, 17, -8, -12, 16, 6, -3, -7, 4, 5, -18, -14, -10, -4, 4, 27, 3, 3, -18, -5, -8, -18, -14, 15, 9, 24, -3, -1, -1, 3, 6, 9, -1, 28, -13, -29, 5, 7, -9, 6, 4, -7, -12, 20, -25, -44, 5, 23, 12, 11, 7, 17, -1, 24, -28, -49, 11, 21, 25, 16, -11, 3, 5, -12, 3, -29, 22, 10, 4, -9, -14, -5, 7, -19, 25, -3, 25, 11, 9, 1, 10, -16, -15, -21, 3, 17, 22, -9, -12, 10, 10, -1, 9, -16, 12, 33, 13, -4, -24, 16, -10, 8, 21, -3, 5, 27, 19, -35, -25, 0, 3, -6, 23, 4, 1, 25, -8, -25, -24, -1, 0, 10, 13, 9, -3, 7, -20, -15, -12, -4, -2, -8, 14, 17, -4, 19, -15, -22, -5, 0, 21, 12, 3, 5, -14, 9, 2, -9, -26, -9, 8, -5, 18, -6, -14, 19, 14, 0, -29, 4, 11, 16, 4, -11, -4, 7, 5, 8, -4, -7, 12, 3, -15, -12, 3, -11, 9, 5, -4, -8, -4, 2, -22, -14, 21, -8, -1, 2, -9, -14, 2, -3, -18, -3, 7, -1, -2, 14, -12, -23, 10, -8, -15, 4, 22, -21, -1, 5, 13, -10, 5, -5, 3, -9, 5, -9, 4, 0, 10, -5, -11, -8, -10, -15, 6, -1, -2, -5, 12, 0, -1, 1, -12, 1, 9, 4, -2, -7, -5, 18, 3, -7, 13, -5, -6, 10, 2, -12, 1, 18, 0, -5, 11, 4, 1, 2, -20, -20, -3, 17, 28, -8, 34, -6, -2, -12, -9, -7, -15, 16, 22, 10, 23, -2, -3, -4, -4, 6, 0, 23, 24, -10, 12, 6, -2, -8, 9, 5, 7, -2, 10, 10, 6, 23, -7, -32, 13, 1, -10, 20, -2, 15, 20, 25, -32, -58, 34, 7, -20, 5, -3, 14, -3, 14, 0, -43, 46, 18, -19, -14, 4, 8, -4, -7, 1, -31, 55, 14, -19, -12, 8, 9, -26, -22, 11, 25, 29, -6, -39, -14, 20, 0, -23, -9, 16, 31, 1, -8, -24, 5, 9, -8, -13, 7, 5, 32, -19, -12, -10, -3, 12, -6, -10, -3, -8, 27, -10, 3, -6, 12, -5, 11, -10, 17, -6, 12, -8, 4, -4, 17, -14, 2, 3, 12, -4, 2, -2, -1, -3, 21, -18, -7, -13, 14, -1, 9, -10, -11, -15, 16, 0, -11, -10, -7, -4, 6, -9, 12, -4, -3, 3, 9, -2, -5, -10, 7, -16, -1, 4, 11, -9, -6, -12, -8, -7, 1, 0, -6, 13, 15, -5, 2, 17, 4, -17, 6, -4, 7, 0, 6, -9, -5, 16, -1, -9, -5, 3, -4, 1, 4, -4, 5, -1, -14, 3, 14, 11, 10, 3, -5, 1, 2, -2, 4, -15, -5, 5, -6, 8, -9, -3, 4, -7, -10, -31, 7, 17, 10, -14, 3, 14, 0, -6, -28, -28, 17, 17, 11, -21, -16, -5, -3, -12, -21, -14, 26, -3, -8, -1, -11, -2, -4, 0, -24, -12, 16, 11, 6, -13, 8, -4, -9, 5, -7, -12, 25, 1, 7, -4, -5, 12, -5, -14, -12, -16, 16, 10, 22, 3, 9, 7, 9, -12, -23, 9, -3, 8, 18, -12, -5, 6, 7, -4, -2, 6, -14, 19, 12, 5, -7, 9, -10, 1, -3, -3, -17, 14, 4, 7, 2, 16, -6, -4, -13, -4, -8, 27, -11, -12, -8, 10, -5, 4, -13, 7, 2, 18, -1, -7, -10, 0, -15, -10, 2, -2, -1, 17, 5, -4, -7, -1, -4, -4, -12, 4, 12, 21, -7, -4, -7, 12, 0, 13, -12, 13, 2, 12, -3, -30, -4, 6, -10, 3, -12, 5, -21, -16, -3, -11, -2, 7, 5, 5, -12, -10, 2, -7, 17, -2, 13, 3, -6, -17, -22, 1, -3, 7, 19, 10, 3, -17, 9, -3, -10, -7, -9, 7, 4, 8, -4, 0, 10, 0, -6, -15, 6, 16, -16, -1, 14, -7, -11, -8, -1, -15, 12, 3, -5, -4, 7, 3, -11, -8, 6, -7, -10, 7, -18, -10, -11, 11, 3, -19, -7, -16, -2, 0, -4, -10, -12, 12, 1, -17, -4, -22, 16, 5, 4, -18, 1, 5, 13, -17, -9, -5, 2, 24, -6, -3, -9, -1, -7, -5, -6, 11, 5, 1, 3, 1, 4, 15, -9, 20, -3, 8, 16, 8, 7, -1, 12, 1, -9, 22, 17, 13, -2, 5, 7, -11, 5, -10, 15, -8, 13, 2, 2, 2, 3, -6, -4, 7, -4, 3, 10, -7, -5, -3, -1, -18, 7, -3, -2, 19, 0, -11, -2, -1, 13, 12, 1, 12, -15, -2, 0, -9, 8, -6, 11, 6, -11, 10, 7, -6, -20, -8, 12, 8, 4, -4, -19, 7, -10, -1, -19, 2, 23, 11, 8, -2, -10, 11, 1, -11, -18, -22, 12, 0, 15, -4, -13, -2, -1, -12, -23, -4, 14, 6, 11, 2, 5, 5, -14, -14, 10, -11, 22, 1, 11, -3, 7, 0, -11, -23, 10, -20, 3, -5, -1, 3, -5, -9, -9, 6, 5, -10, 16, 13, -37, -3, -7, 2, 15, 13, 28, -29, 4, 1, -35, -4, -8, -12, 15, 18, 17, -14, -10, 0, -30, -2, -3, -8, 14, -9, 2, 8, -12, -3, 5, -10, 2, -7, -8, -19, -4, 1, 2, 3, 20, -21, -17, 19, 4, -20, -6, 15, 8, 5, 36, -14, -1, 13, -7, -13, -16, 16, -3, -8, 26, 2, -19, 3, 6, -13, 2, 4, -19, -11, 38, -9, -8, -11, 10, 5, -12, 8, -11, -11, 23, 8, -2, -7, 19, 3, 4, -8, -8, -12, 7, 3, -3, -2, 12, 1, -2, -17, 1, 5, -11, 12, 3, -19, -10, 24, 8, -13, 12, -5, -18, 6, -9, -7, -7, -15, 9, -17, 9, -2, 4, -10, -8, 19, -4, -6, 17, 1, 10, 1, 12, -22, -7, 13, -7, -3, 7, 6, -8, -10, 24, -6, 11, 24, 0, -21, -7, 8, -3, -19, 17, 29, -10, 10, 10, -19, -24, 21, -2, -26, 5, 25, 12, -10, -1, 2, -12, -12, 10, -28, 2, 15, 9, -12, 13, 4, -28, -28, 27, 1, -26, 6, 14, -9, 5, -2, 3, -16, 14, 24, -14, -18, 20, 10, -11, 10, -2, 5, 20, 10, 7, -1, 11, 3, -15, -6, -5, -13, 22, 9, 8, -2, 21, -16, 14, -7, 1, 4, 5, 0, 15, -3, 1, 0, 7, -1, 14, 16, -18, 2, -5, 14, 27, 22, 9, 6, 30, 10, -38, -8, -22, 12, 15, 9, -6, -14, 19, -6, -17, -1, 6, 12, -9, 4, 7, -3, 0, -15, 0, 2, 13, 25, -4, 1, -5, -1, -19, -20, 7, 9, 16, 10, 15, -4, 13, 13, -29, -7, 1, 16, 20, 23, -7, -6, -2, -3, -15, 8, 11, 16, 22, -7, 3, -9, -17, 9, -11, 7, 8, 1, 6, -5, 11, 10, -12, 6, 9, 12, -18, 5, 10, -11, 5, 0, 9, 10, 14, 5, -1, 0, -2, -10, -7, 11, -11, 12, 24, 1, -5, -11, -25, 11, -10, 11, -10, 9, 3, -5, 7, -12, -5, -8, -12, 13, 14, 4, 6, 6, 13, 10, 2, 4, -4, -6, 6, -10, -20, 9, 7, -10, 15, -9, -7, 0, -6, -19, 15, 7, -11, 3, -3, 5, -10, -9, 1, -2, 12, 5, -5, 0, 3, 5, 8, -5, 11, -15, 4, 4, 3, 11, 9, 10, -6, -13, 11, -2, -26, -4, -5, 16, 3, 0, -3, -26, 13, 21, -14, -9, 10, 4, -3, 5, -4, -6, 3, 30, -14, -12, 20, 16, -32, -18, 11, -3, -8, 4, -18, -8, 19, 12, -23, -16, 13, 9, -14, 19, -14, -1, 23, -5, -13, -6, 9, 25, -13, -11, -18, 6, -3, 8, 11, 11, -6, 16, 0, -17, 1, 8, -4, -3, -3, 18, 11, 0, -9, -18, 4, 6, 2, 21, 17, 6, 19, 17, 8, -14, 9, -7, 2, 31, 1, 13, -10, 7, -4, -6, 21, -9, 0, 11, 4, 3, -21, 9, 12, -7, 15, 3, -4, 19, -10, 6, -17, -17, 4, -3, 3, 3, -9, 13, -11, -3, 9, -18, -2, 8, -22, -15, 10, 33, -17, -4, 9, -7, -5, 6, -31, -19, -3, 24, -15, -29, 7, -7, -7, 13, -17, -2, 12, 32, 15, -17, 2, -1, -3, 9, -25, -3, -4, 25, -5, -7, 0, -13, 8, 1, -18, -4, -16, 22, -5, -13, -2, -12, 3, 4, 3, 19, -12, -8, -11, 8, -2, -29, 3, 3, 0, 26, -7, -14, 3, 5, -17, -19, -6, 7, 16, 22, -7, -25, 9, 9, -18, -21, -8, -13, 20, 6, -19, -27, 3, 8, -13, -14, 7, -11, 27, 16, 5, -15, 0, 9, -13, 4, -5, 5, -11, 13, -14, 10, -14, 9, -10, -10, -3, 12, -5, 5, 11, -3, -16, 17, -2, -5, 9, 18, -18, 15, 20, -17, 10, 10, -3, 7, -1, -2, -35, -4, 35, -20, 23, 5, -9, 4, 4, 16, -37, -2, 41, -1, 24, 15, -12, -2, -9, 3, -17, -4, 13, 16, 43, 14, -11, -2, 15, -10, 3, -13, 0, 24, 35, 1, -20, -4, -2, 10, 27, -19, -34, 11, 19, -10, -1, -1, 12, -2, 28, 1, -35, -11, -9, -4, 6, 10, 2, 2, 8, 8, -34, -11, -19, -5, 19, 22, -4, 11, 8, 0, -23, -20, -10, -9, 19, 10, 2, 18, -10, -7, -2, -11, -9, -3, 2, -6, 9, 15, 4, -2, 13, 14, 25, 9, 9, -17, 16, 4, 4, 2, 5, 7, 30, -8, 4, 4, -3, -14, 20, -3, -14, 0, 22, 0, 1, -3, 0, -31, 19, 1, 10, -10, 17, -3, 4, 15, -16, -26, 3, 15, 8, -14, 10, -3, -1, 9, -12, -11, -5, 2, 28, -9, 13, 0, -5, 5, 0, -23, 12, 5, 28, -2, 10, 15, -11, -7, 7, -24, -7, -1, 14, -3, -12, -2, 3, 3, 0, -9, -1, 8, 5, 1, -10, 2, -8, 10, -4, -10, 1, 11, 10, -3, 6, -13, 3, 11, -10, 3, 2, 13, -3, -1, -2, -4, 3, 1, -1, 9, 4, 14, 8, -4, 0, -13, 3, -4, 0, -4, -1, -3, 7, 16, -16, 0, -3, -3, 10, 3, -2, 10, 20, 6, 8, 0, 8, -13, -9, -10, -7, -7, 3, 6, -2, 0, -3, -7, 9, -13, 7, 4, 9, 1, 18, 0, -3, -11, -5, -7, -10, -16, 6, 26, 14, 10, -2, -18, 17, -9, -17, 3, -3, 7, 19, 7, 13, -14, -3, 19, -19, -31, 0, 8, 5, 1, 11, 3, 1, 26, -18, -43, 13, 13, 3, -2, -2, 9, 14, 29, -11, -42, 27, 23, -11, -13, 5, 1, -5, 33, -5, -41, 34, 11, -18, -18, 16, 4, 4, 28, 12, -24, -1, -2, -4, 0, 1, 1, 7, 10, 14, 0, -7, -24, -8, -9, -6, 15, 6, -5, 13, 1, -3, -23, -12, -1, -7, 1, -7, 8, 18, 40, 0, -21, -34, -9, -18, -3, 8, 4, 11, 51, -2, -24, -35, 4, -26, -21, -12, -3, 20, 47, -12, -4, -38, -9, -27, -31, -15, 12, 27, 34, -13, -5, -17, -8, -25, -11, 7, -2, 2, 31, -14, 7, -3, 2, -20, -6, 5, -17, -4, 7, -8, 14, -3, 7, -10, 4, -15, -12, -11, 6, 2, 16, 12, 5, -6, 16, -15, -20, -16, 2, 0, 3, 5, 3, -11, 11, 9, -19, -9, -7, 5, -5, 4, 9, 7, 14, -10, -17, -11, 6, -1, -4, 3, 2, 17, 12, 0, -6, 3, -9, -6, -3, 0, -3, 18, -2, -1, 3, 16, -10, -8, -11, 0, -3, 3, 9, 7, -8, 4, 1, -5, -8, 0, 0, -10, -4, 8, -6, 6, -19, 5, -2, 4, -8, -6, 8, -7, -1, 13, 2, 7, -11, 17, -11, 11, 4, -2, -6, 14, 15, 14, -12, 16, -14, 2, 14, 8, -8, 7, -6, 35, -1, 27, -25, 6, 22, -7, -19, 9, 5, 12, -14, 16, -15, 31, 30, 10, -11, -18, 11, 6, -8, 20, -4, 29, 11, 15, -7, -9, -2, -31, -15, -6, 4, 14, -4, 20, 31, 12, -7, -66, -26, -15, 28, -5, -4, 17, 24, 10, -5, -25, -15, -8, 12, 6, -6, -13, 6, -19, -13, 3, 16, 2, 1, -19, -2, -6, 5, -20, 6, 20, 14, 13, 6, -18, 1, 3, -20, -17, 4, 32, -1, 8, 5, 9, -3, -17, -32, -2, 15, 9, 1, 23, 2, -4, -3, 3, -23, -4, 10, 20, 9, 8, 3, -2, 12, -9, -12, 14, 21, -12, -2, 9, 11, 2, 2, -9, 7, 5, 8, -33, -19, -15, -8, 0, -4, 4, 15, 1, 18, -17, -32, -13, -8, -8, 1, -7, 14, -9, 9, -1, -10, -2, -5, -3, -3, 5, 9, -13, 1, 12, 32, -13, -9, -11, -2, 9, 0, -1, -15, 7, 22, -21, -4, -8, 2, -4, 19, -18, 4, -7, 29, -5, -8, -18, -9, -9, -4, -20, -11, 0, -2, -12, -5, -16, 18, -9, 2, -1, -5, -11, 14, -9, 12, -7, 14, -4, -5, 9, -1, -7, 10, 7, 16, -1, 12, 3, 14, -1, -3, 0, -2, 3, 5, 10, 9, -5, 8, -1, -13, 8, 8, -11, -4, 6, 3, -1, 9, -8, -14, 8, 13, -5, -2, 2, 7, -9, 3, -19, -14, 9, 12, -2, -3, 2, 20, 9, 17, -2, -24, 8, 10, -11, -9, 5, 13, 4, 15, -10, -28, 22, 7, -16, -3, 0, 15, -5, 5, -7, -33, 14, 3, -1, -7, 2, 21, 4, 1, -9, -19, 21, 10, -10, -10, 8, 9, 6, 2, -6, 4, 7, 0, -5, 6, -6, -3, 17, -8, 6, 25, -20, -18, -10, 12, -7, -5, 11, -1, 13, 25, -15, -28, -24, 7, -16, -14, 6, -3, 25, 48, -11, -30, -23, 2, -14, -1, -9, 7, 20, 49, -4, -8, -14, -3, -10, 0, 3, -21, 1, 30, 4, -13, 2, -10, -17, 6, -19, -20, 9, 20, -5, 13, 10, -5, -2, -3, -19, -15, -10, 10, -5, 12, 14, -6, 6, 18, -11, -11, 1, -12, 3, 31, 20, 14, 5, 13, -3, -3, -17, -42, 11, 24, 5, 6, -5, -2, 8, 15, -5, -26, 2, 37, 8, -3, -8, 9, 5, 9, -6, -19, 15, 23, -2, -5, -8, -4, 10, 21, 6, -15, 12, 5, -18, -6, -18, 4, -4, 6, -3, 8, 13, 14, -8, 5, -10, 0, 0, 4, 6, 2, 0, 9, -2, -7, 13, 2, -5, -10, -2, 13, 13, 15, -3, 0, -2, 4, 12, -14, -12, -4, -3, 0, 1, 3, 5, -3, 3, 1, -12, 6, -7, -9, 13, -2, 0, 8, -10, 4, -18, 11, 11, 17, 9, -10, -4, 5, 0, -4, -26, 13, -6, 7, 19, -2, -3, -11, 9, 3, -25, -9, 17, -9, 10, 10, 16, -13, 3, 17, 3, -2, -13, -31, 5, -2, 22, -15, 22, 31, -7, -16, 2, -45, -16, 8, 9, -5, 17, 31, 24, -12, -14, -60, -6, 8, -5, -7, 0, 17, 20, -26, -2, -59, -18, 12, 16, 4, -6, 11, -1, -10, -8, -43, -34, 1, 25, 0, 17, -2, 1, -18, 11, -4, -9, -10, -5, -12, 4, 10, -15, 4, -1, 4, -5, -13, -26, 3, -7, -6, -13, 2, 6, 24, 18, -23, -36, -1, -6, -16, -8, -11, 12, 27, 23, -21, -7, -6, 0, -17, 10, -8, 1, 26, 5, -18, -7, 14, -1, 4, 5, -7, 5, -6, -1, -16, -9, 1, -16, -3, 4, 2, -11, 5, 17, -9, -9, 7, -13, 4, 2, -1, -4, -5, 5, -4, 8, 18, -13, -13, 2, 8, 19, 8, 1, -9, 21, 0, 3, -10, 6, 12, 2, -4, 2, 2, -5, 8, -6, -3, 17, 21, -13, 5, 17, -16, 16, -5, 12, 2, 14, 1, 12, 8, 2, -8, -8, 3, -10, 1, 6, 10, -5, -4, -7, -10, -3, 15, 0, -14, -14, 6, 11, 7, -1, -1, 3, 15, 3, 2, -2, 3, 10, 4, 12, -14, 7, 11, -5, -5, -8, 3, -1, -1, 3, -12, 10, 5, 12, -11, -12, 3, -1, 1, -4, -4, 14, 7, 20, 10, -36, -34, -1, 16, 5, 21, -8, -15, 20, 1, -29, -58, 2, 13, 17, 7, -6, -18, 23, 18, -21, -41, -39, 12, 0, 10, -18, -11, 19, 4, -2, -34, -28, 3, 3, -21, 11, 1, -13, 18, 7, -5, -20, -12, 4, -16, 5, 5, 1, 9, 0, 10, 25, -9, -18, -13, 12, 16, -3, -8, 10, 18, 33, -22, -8, -7, 25, 5, -1, -6, -11, 37, 33, -20, 10, -7, 2, -7, -10, -1, 2, 32, 17, -12, 7, -6, 7, 3, 2, -11, -5, 16, -8, -6, 24, 2, -14, -12, 10, -19, 13, 21, -11, -7, 19, -26, -15, 8, -10, -9, 9, 28, -9, 0, 12, -5, -7, 15, -16, 0, 15, 7, 7, 11, 14, -10, 4, 13, -15, 2, -6, 29, -8, 12, 15, 4, 0, 9, 5, -16, -8, 21, 17, 10, 6, 8, 0, 21, -13, -12, -19, 18, -1, -7, -2, -2, -2, 12, -1, -8, -3, 3, 16, -1, -2, -7, 1, -3, -4, 1, 6, 11, 5, -9, 13, 8, -7, 0, 13, -12, -12, -2, 16, 2, 18, -14, 2, 4, 1, -11, 8, 10, 13, -6, 15, -1, 3, 8, -18, -7, -2, -7, 11, 4, -1, -4, -10, 7, 6, -2, 1, -1, -4, -7, -5, 9, 22, 13, -7, 12, 7, -19, -6, -7, 1, 4, 6, 12, 3, -3, -12, -5, -2, 5, 9, 7, 13, 5, -11, 16, 0, -15, 12, -2, 6, 1, 14, 8, 3, 1, 0, -6, 0, -9, -2, 7, -2, -4, 1, 10, -14, 5, -1, -2, 2, -1, 13, -5, -12, -1, -8, 9, 1, 9, -8, -9, -7, 0, -11, -3, 13, 2, 6, 5, -12, -11, -7, -2, -12, 3, 12, 21, -16, -5, -11, -15, 8, 2, 5, -10, 9, 25, -18, 0, 11, 1, 5, 6, 10, -2, -1, 8, -6, -14, 34, 6, 13, -1, 16, -17, -23, -11, -1, -10, 18, 11, 15, -6, -3, 6, -32, -8, 20, 8, 19, 2, 6, -12, -11, -15, -4, -14, -5, 4, -9, 1, -3, 2, -4, 0, 16, 4, 18, -5, -2, -25, -1, -3, -13, -13, 15, 7, 16, 10, -9, -27, 0, -22, 13, -24, 25, 2, 7, 24, -1, -28, -5, -21, 13, -10, 10, 0, -10, 15, -20, -17, -9, -5, 12, 1, 18, 5, -20, 17, -3, 5, 8, 8, -3, 11, -6, -27, -22, 6, -12, -6, 22, 21, 4, 9, 8, -24, -17, 10, -12, 15, 24, 30, 1, 17, 10, -35, -12, -5, -10, -8, 20, 38, -1, 17, 19, -35, -22, -11, 10, -6, 28, 37, -7, 9, 11, -16, 3, -20, -13, -12, 12, 14, 9, 8, 16, -7, 18, -6, -1, 8, -7, 8, -13, 7, -1, 6, 21, -20, -4, -1, 2, -10, 1, -6, 5, 5, 4, -24, 8, 2, 1, -8, -7, 9, -5, 2, 3, -10, 0, 8, -13, -31, 10, 17, -23, 3, -2, -7, 2, -6, -12, -10, 7, 1, 7, 13, -1, -8, -9, -4, -2, 6, 8, 9, -3, 1, 3, -3, 2, 0, 6, -3, -9, 13, -5, -6, 3, -4, -6, -1, -3, 4, -12, 2, -9, -2, 1, -4, 7, -2, 1, -9, 12, -7, 13, -25, 15, 0, 0, -20, 17, 5, -11, 5, 2, -29, 6, 5, 5, -21, 10, -3, 2, -5, 14, -14, 1, 6, 6, -14, 0, -1, -14, -10, 11, -1, 12, -7, 19, -11, 16, -11, -8, -14, 7, -20, 27, -8, 6, 10, 15, -14, 7, -13, 10, -24, 19, -5, 4, 36, 16, -24, 7, 9, 22, 2, -15, -33, -20, 28, 0, -29, 13, 13, 32, -9, -33, -23, -14, 40, -4, -53, 11, 18, 3, -7, -21, -12, 10, 18, -12, -53, 11, 1, -37, -21, 12, 18, 23, 7, -28, -42, -17, -17, -36, 10, 27, 37, 11, -24, -11, -13, -3, -16, -23, 22, 21, 27, 0, -16, -16, -2, -4, 13, -11, 7, 0, -3, 8, -4, -1, -8, -14, 9, 4, 14, -19, -11, -6, 3, -2, 6, 0, 4, 17, 8, -24, -14, -11, 18, 3, 12, 0, 14, 10, 3, -31, -3, -19, 8, 7, 19, 11, 0, 11, -2, -9, -2, 3, -16, 0, 10, 0, -4, 3, -6, -24, 18, 15, -20, 1, 6, -8, 8, -8, 7, -3, 13, 3, -5, -6, 15, 0, -9, 7, 9, -6, 6, -12, -14, -13, 8, 12, 4, -10, 4, 1, -7, -13, -1, -15, 8, 11, 6, 7, -10, -8, 16, -13, -1, -3, -10, -6, 8, -2, -5, 3, 7, -10, 3, -2, 2, 4, 13, 0, -2, -2, 6, -21, 11, 2, -1, -6, -15, 3, 17, -7, 4, 0, 0, 2, 10, -14, 6, 2, 27, -20, -14, 6, -10, -3, 6, -8, -11, -7, 27, -1, -5, -9, 2, -8, 10, 4, 1, 10, 20, 10, -18, 3, -21, -2, -2, -12, -8, 7, 25, -1, -24, -14, -22, 11, 15, -20, -22, 16, 14, 17, 3, 5, -24, 3, 8, -13, -14, -1, 2, 2, -10, 25, -2, 6, 8, 9, -6, -7, 0, -27, -6, 31, 19, 5, -6, 5, -6, 18, -27, -14, -10, 21, 1, 7, -13, 12, 5, 23, -6, -6, -3, 27, -7, 4, -12, -6, 15, 11, -10, 8, 5, 20, 15, 6, -12, -4, 9, -6, -34, 7, 18, 21, 9, 14, 0, -4, 12, 11, -35, 12, 19, 0, -7, 9, 13, -12, 3, 2, -29, -3, 17, -3, 4, 8, 8, 8, 18, -2, -9, -1, 13, -7, 0, 5, 8, 16, 22, -19, -13, 2, 18, -10, -3, -5, 0, 11, 2, -27, 4, 5, 1, -4, 5, -17, -7, 18, -1, -42, 2, 24, 3, -8, 8, -18, -12, 8, -15, -30, 16, 14, 14, 3, -4, -18, 0, 9, -21, -12, 6, 9, 14, -2, 13, -14, 5, -11, 2, -14, 12, -4, 5, -11, 4, -4, 7, 7, -6, 10, -1, 0, -11, -7, -9, -6, -4, -16, -2, 0, 18, 1, -3, 9, -7, 0, 11, 3, 5, 0, 4, -2, -4, -4, 6, -1, 5, 14, -5, -4, 6, -16, 10, -17, 1, -3, -4, -9, 13, 17, 3, -9, 0, -14, -18, -6, -2, 9, -4, 5, -9, -15, -10, -21, -5, 7, 5, 4, -8, 15, -5, -11, 10, -13, -14, 6, 13, -14, 7, -11, 1, 8, 6, 0, -11, -4, 7, -12, 18, -16, -1, -11, 2, 5, 0, -11, 14, 2, 22, 3, 11, -7, -5, -15, -13, 1, 6, -10, 33, -3, 19, -14, -4, -24, -17, -7, -28, -8, 7, -5, 20, 4, 0, 9, -19, -2, 3, 6, -2, -7, 8, 11, -1, 1, -10, -13, 1, 0, -1, -7, 18, 3, 4, -4, -23, -1, -2, -3, -17, -5, 1, 3, 20, 3, -22, -5, -4, 1, -22, 4, 4, -1, 9, 11, -28, 3, -9, 1, -10, 12, -10, 4, 6, 1, -15, 3, 13, -2, 1, -7, 10, -13, -4, 7, 2, -3, -6, 12, 11, 5, 17, -24, -15, -20, -7, 3, -9, 4, 13, -5, 2, -20, -20, -15, -8, 0, -1, -1, 5, -5, 7, -4, -31, 5, -12, -1, 3, -5, -4, -6, -12, 4, -16, -3, -7, 7, 3, -9, 2, -3, -14, 2, -7, 1, -19, 6, 4, -11, -13, -13, -13, 10, -4, 0, 12, 18, 0, 3, -9, 6, -20, 17, -6, -5, 20, 8, 0, -5, -12, -5, -8, 7, 8, 7, 3, 20, -7, -5, 12, -4, 9, -1, 5, 14, 9, -5, 3, 16, 10, -14, 0, -4, -9, 14, 28, -3, 6, -8, 6, -13, -7, 7, -12, 0, 18, 9, -11, 10, -5, -7, -18, 8, 2, -1, 14, -7, 10, 2, -4, 15, 9, -1, -19, 2, 3, 2, 5, -14, -10, -2, 2, 1, -2, 16, 6, 11, 12, -8, -2, 1, 20, -4, 4, 14, 10, -5, 0, 7, -22, 0, 26, -16, 0, 10, 25, 9, 2, -15, -8, -9, 34, 4, -3, -3, 7, -15, 11, -18, 4, -6, 21, 17, -8, -6, -7, 2, -7, 0, -18, -14, 23, 23, 9, 2, -4, -7, 6, 5, -10, -10, 17, 2, 14, 1, 0, 2, -7, 15, -8, -7, 12, -9, 15, 6, -10, 10, -21, -4, -2, -30, 6, -14, 17, 19, 11, -2, -22, 17, -1, -27, 10, -21, 12, 47, 3, -27, -20, 14, -16, -9, 0, -10, 12, 52, -4, -36, -18, -6, 8, -1, -22, 20, 7, 13, -5, -7, -5, 10, 6, 2, -42, 38, 12, -14, -16, 14, -6, 0, 28, 7, -36, 42, 2, -21, -31, 25, 8, -7, 15, 10, -38, 33, -1, -27, -22, 12, 6, -5, 4, 21, -5, 11, -9, -14, -19, 0, 10, -11, -15, 8, 26, -1, -22, -13, -15, -1, 4, 13, -11, 17, 7, -8, 2, -10, -16, 0, -2, 0, -13, 11, 16, -9, -7, -3, 1, -3, -5, -4, 14, -8, 16, -19, 7, 6, 14, -12, 1, -8, 9, 1, -11, -12, -18, -3, -7, -2, -10, -7, -18, 6, -14, 2, -6, -10, 7, 4, 7, 3, 3, -8, -12, 4, -22, 4, 2, 4, 7, -15, -20, -3, -10, 7, -15, 3, -4, -10, -1, 1, 0, 0, -6, -1, 9, 8, 14, -12, 4, -3, -10, -16, -13, 7, -2, 4, -14, -8, 15, 11, -15, -1, -14, -6, 4, 9, -7, -12, 5, -13, 0, -13, -7, -1, 11, -4, 2, -17, 13, 9, 5, -3, 15, -5, 4, -7, 1, -1, 6, -9, -8, 2, -1, 5, 4, -15, -6, -9, -6, -5, -11, -19, -1, 24, 10, -34, -9, 6, -1, 10, -10, -12, 10, 20, -8, -19, -17, 21, 3, -11, -19, 5, 1, 19, 16, -12, 6, 23, 22, 4, 0, -5, -21, 22, 27, 12, -3, 25, 32, 3, -6, -2, -19, 11, 29, 10, -5, 35, 36, 8, 29, -4, -15, -17, 16, 27, -5, 41, 46, 14, 36, 1, -9, -10, 1, 25, 2, 24, 37, 7, 18, -7, -7, -5, 17, 32, -5, 2, 30, 14, 16, -15, 10, 2, 10, 23, 0, -4, -1, -1, -8, -4, 20, -8, 1, 15, -5, -7, -10, -1, 6, 17, 4, -22, -5, -12, -21, 0, -7, 7, 7, 17, 22, -8, -12, -9, -12, 0, -7, 5, -2, 24, 2, -16, -23, -3, 4, -9, -9, -8, -4, 21, 13, -15, -18, -14, 1, -5, -6, -2, 15, 21, 20, -14, -18, -18, -8, -10, -5, -5, 3, 2, 18, 7, 12, -1, -12, 1, -4, -3, -3, 8, 13, -2, -1, -8, 13, 1, 11, -13, -21, -7, 4, 10, 4, 6, 2, -19, 6, -9, -19, -25, 8, 14, 4, 1, 6, -12, 22, -5, -21, -20, 7, 3, 13, 9, 18, 3, 4, 5, -8, -2, -4, 9, 24, -12, -1, -14, -10, 12, 1, 24, -12, 2, -10, -37, -16, -18, -34, 5, 7, 44, -2, -16, 5, -41, -23, -23, -28, -2, 17, 33, -19, -29, 13, -18, -2, -41, -20, 4, -6, 11, -14, 0, -11, -7, -13, -32, 3, -7, 0, 9, -20, -9, 12, 10, -5, -12, -6, -4, -8, -7, -12, 4, 7, 21, -4, -6, -3, 6, 14, -7, -21, 3, -16, 11, -13, 21, 21, 17, 20, 3, -18, 3, -15, 11, 5, 17, 8, -3, 22, 1, -12, 1, 13, -9, 8, 15, 14, -4, -2, -24, 15, -2, 20, 10, -4, 28, -8, 2, 8, -13, 12, 23, 6, 3, 11, 21, -15, 11, -3, -19, 17, -4, -2, 6, 18, -3, -2, -7, 7, -19, 16, -10, 15, 1, 11, 7, -2, -4, 2, 8, -3, -22, -1, -9, -5, 18, -9, 4, 6, -6, 23, -9, 10, -7, 6, -10, -4, -12, 9, -4, 8, -6, 14, -11, -5, 5, -7, 1, 0, 9, 7, 15, 6, -6, 6, -9, -4, -2, -4, -6, 7, -2, -2, -15, 11, -16, -4, 9, 2, 5, 7, 6, 1, 8, 4, -18, -3, 2, 4, 7, 5, -2, 2, -11, -12, -1, 6, -11, 0, -3, 12, -6, 1, 10, -1, -10, 5, -2, 14, -1, -4, -2, 15, 12, -14, 5, 12, 10, 7, 4, -18, 10, -5, 9, 1, 10, -13, 8, -9, 4, -15, 1, -2, 5, -3, 9, -8, -6, -3, 20, -2, 6, 7, 22, -1, 10, 15, -22, -31, 17, 6, 18, 9, 28, 0, 16, 12, -1, -17, 21, 0, 6, 8, 2, -8, 14, -2, 11, 20, -2, 12, -5, 3, -20, 14, -4, -12, 11, 27, -10, 11, -23, -11, -3, 16, -12, -14, 11, 26, -1, -8, 4, -4, -2, -8, 3, -25, -16, 2, 13, -1, 3, -1, 3, -20, 1, -3, 9, -16, 8, -10, 16, 13, -9, -16, 6, -10, -7, -3, -13, -12, -12, 4, -2, -9, 14, -10, 10, -11, -10, -17, 6, -12, 11, 7, 24, -3, -16, -10, 6, -8, -3, -5, -1, 17, 13, -7, 6, -4, -13, 2, 6, -17, -11, 37, -4, -27, 10, 17, -27, -2, 11, -15, -8, 33, -8, -25, 14, 15, -17, 1, 6, -6, -2, 10, -8, -25, -6, 8, -11, 0, 6, 15, -17, 12, 0, -16, 4, -19, 14, -1, -4, 12, 6, 2, 8, -8, -14, -14, -6, -2, 2, 15, 3, 5, 7, 8, -5, -8, 1, -3, -2, 12, -5, 8, 14, 1, -3, 0, 0, -2, -5, 13, -7, -10, -1, 10, 6, 10, -8, 10, 2, 5, -3, -1, 0, 1, -1, -6, -7, -7, 7, 6, 1, 2, 0, -4, -10, -21, 5, -1, 3, 6, 12, 5, 18, -4, -3, -5, -4, -19, 1, 10, 16, 7, 13, 2, 0, -20, -19, -16, 5, 10, 16, 6, 0, 15, -9, -12, -10, -21, 0, -2, 7, 12, 4, 17, -5, -4, -18, -8, 19, -10, -4, 20, -9, -5, 12, 16, 1, 4, -2, 1, -2, 14, -29, -8, 11, 20, 21, 7, 6, 0, -23, 13, -33, -16, 8, 15, 38, 4, 9, -3, -23, -19, -27, -17, -1, 17, 34, 6, 7, -3, -26, -28, -27, -10, -1, -3, 26, 22, 0, -9, -4, -10, -17, -5, 6, 8, 9, 31, -9, -15, 25, -4, -8, 1, -12, -2, -10, 39, -8, -14, 33, 16, -28, -21, 10, -1, -24, 19, 11, -14, 14, 28, -22, -12, 17, 3, -21, 13, 7, 6, 2, -1, -13, -12, 18, 15, -7, -13, -3, 8, -21, 13, -2, -19, 3, 10, 29, -15, -17, 6, -28, -2, 2, -2, -1, -18, 18, -10, -12, -2, -15, 16, 6, -11, -11, -13, 5, -28, -13, -1, -15, 2, 4, 2, -7, 6, 1, -10, -3, 13, -5, 3, 5, -4, -14, 4, -6, -4, -1, 2, -6, -3, 9, 9, 11, 6, -1, -3, 1, 14, 0, -8, 4, 8, -4, -16, -11, -5, -3, -2, 6, -15, 4, 10, -11, 7, 1, 8, -1, -4, 6, -6, 4, 17, -2, -2, -6, 6, 9, 3, -19, -3, 0, 1, -9, 14, -9, 20, -7, -3, 10, 15, 6, 18, -13, 4, -1, 9, -5, -6, -2, 1, -3, 9, 2, 23, -12, -10, 7, 1, -13, 5, 4, 9, -3, 11, -19, -19, 4, -3, -4, 4, 1, 1, 1, 4, -4, 4, 2, 1, -20, -5, -11, 6, -9, -7, 13, -3, 16, -1, -5, -5, -5, 7, 8, -4, -2, 2, 14, 17, 15, -11, -19, -6, -5, -5, 7, -16, 12, 13, 8, -5, -11, 21, 13, 4, -11, -19, 2, 26, 7, -31, -5, 16, -13, -19, -14, -13, 11, 14, 11, -20, -11, 28, 9, -8, -21, 6, 24, 18, -19, -34, 4, 20, 16, -12, -28, 27, 21, -7, -25, -14, -8, 25, 1, -7, -22, 50, 7, -31, -4, -6, 0, 20, -2, 4, 3, 43, 4, -27, 3, 6, -16, 5, -2, -11, -4, 29, -23, -27, 18, 12, -7, 6, 0, -1, 2, 13, -17, 6, 12, -8, 10, 4, -19, 6, 19, 5, 6, -21, -16, -17, 4, 12, -6, 2, 38, -7, -13, -3, 6, -7, 23, -1, -11, -4, 36, 0, -36, 0, 16, -12, 1, -8, 11, -9, 20, -4, -37, 13, 24, 7, -18, 4, 1, -5, -10, 16, 3, 1, 8, 17, -21, -6, 11, -4, -18, -6, 19, 11, 3, -9, -17, -6, 1, -7, -29, -9, 21, 19, -4, -5, 8, -6, 8, -2, -14, -10, 34, 6, 4, -15, 14, -14, 5, 3, -34, -4, 33, 5, -3, 8, 12, -12, -9, -15, 2, -9, 8, -6, 8, -1, 9, 11, -12, -16, 4, -11, -2, -3, 2, 8, -1, 8, 12, -14, -12, 0, -11, -5, 13, 4, -6, 14, 12, 15, -22, -8, 10, 5, -19, 4, -11, -9, 11, 6, -19, -19, 18, 6, -15, -20, -21, -11, 15, 3, 5, -20, 10, 16, -9, 2, -11, 6, -6, -15, -6, -4, 13, -1, 3, 9, -10, -3, 4, -18, -11, 10, -1, 9, 12, 13, -7, 7, -21, -23, -2, 5, -3, 16, -1, 13, -16, 5, -16, 2, -12, 2, -12, 11, -19, 8, 5, 11, -12, 15, -17, 10, 11, 12, -17, -16, 5, 5, -3, 18, -4, 3, 4, -7, -18, -10, -1, 10, 1, -5, 14, 7, 10, -12, 18, 3, -49, -5, 15, -19, 14, -2, 23, -1, 27, 7, -43, -15, 3, -6, 13, -5, 25, -12, 38, 3, -26, -13, 11, -9, -11, -13, 27, -3, 24, -3, -14, -6, -8, 2, -7, -2, 23, 4, 6, 3, 10, -1, -3, 20, -1, 4, 0, -10, 7, -2, 15, -5, -2, 25, 19, 20, -20, -11, -13, -10, 29, 5, 15, 31, 19, 9, -35, -14, -3, -10, 18, 3, 3, 30, 12, -1, -26, 2, -2, -4, 10, 1, 12, 8, 9, 0, -18, 11, -4, 2, 11, 5, -13, -11, -7, -10, -9, 13, 4, -11, -5, 17, -3, -15, -11, -17, -7, 6, 11, -4, 9, 7, -3, -2, -13, -7, 3, 20, 9, 14, 12, 8, 3, -8, 5, 3, 8, 4, -9, 4, 2, -8, 2, 4, -5, -11, 9, 8, 6, 1, 4, 11, -3, 1, -1, -14, 10, -6, 4, 3, -15, 12, 4, -9, 6, 4, 8, -9, 9, -7, -13, -4, -2, -7, 7, 6, 2, -16, -8, 8, 8, -3, -16, -8, -16, -9, 11, -13, 6, 3, 17, 12, 10, -6, -15, -3, 17, 9, 4, -5, 22, -1, -11, -2, -15, 3, -1, 0, 2, 7, 20, 9, 2, 5, 20, 1, -28, 6, 2, -4, 19, -12, 3, -7, 31, 38, -36, 13, 4, 3, -22, 15, -13, -2, 12, 49, -24, 20, 16, -12, -53, -17, 6, -10, -2, 22, 24, 13, 17, 5, -54, -33, 12, -9, -18, -32, 31, 10, -2, 21, -14, -36, -5, 16, -13, -45, 36, 28, -27, 37, 16, -45, 8, 7, -18, -28, 16, 23, -12, 34, 43, -34, 1, 26, 0, -9, -23, 7, -6, 23, 36, -26, -8, 24, 22, 1, -34, -10, -23, 19, 35, -24, -12, 18, 10, 29, -13, -19, -31, 3, 28, 0, -6, -2, -7, 19, -20, 5, -15, -12, 18, 9, -9, -3, 1, 20, 0, 21, -18, -18, -3, -7, 10, -14, -15, 10, 17, 18, -12, -12, -9, -5, 0, -14, 4, -10, -14, 23, -14, 10, 3, -13, 9, 11, -8, -17, -3, -5, -1, 17, 6, -16, 6, 0, 12, -13, 7, -10, 4, -13, 12, -16, 4, 5, 10, -1, 1, -8, -4, -1, 2, -6, -7, -5, -3, -4, 13, -8, 0, 3, 5, 25, -7, 14, -16, 2, 9, -7, -2, -2, 3, 29, -1, 13, -35, -8, 18, 14, 17, -12, 8, 10, 1, -6, -42, -7, -1, 27, 19, -10, 3, 18, 19, 11, -37, -24, -19, 44, 33, -32, 7, -3, 8, 5, -2, -11, -32, 24, 10, -29, -3, 3, 21, 17, 25, 6, -53, -3, 1, -27, 7, -11, -11, -5, 25, 1, -17, -23, -16, -7, 17, 4, -4, 2, 8, 10, -8, 4, -12, -1, 4, 19, -9, -6, 10, 15, 9, -23, -1, 7, 3, 15, -3, -18, 11, 4, -6, -14, 13, 1, 6, 12, -1, -15, 17, -5, -2, 2, 2, -9, 1, 12, 11, 4, 15, -4, -8, 6, 4, 1, 7, -5, -4, -5, 2, -10, 1, 15, 14, -1, -1, -12, -12, 1, 1, 3, -5, 8, -2, 7, -8, -10, -3, -9, 16, 18, -5, -1, -3, -14, -10, 0, -17, -10, 5, 2, -9, 7, 1, 4, 7, 5, -9, 5, -25, -3, 16, 17, -11, -10, 8, 1, 13, 10, -4, -24, -2, 26, -2, -3, -2, 4, 3, 3, 10, -34, -4, 10, 9, -4, 5, 8, -2, 10, 1, -8, -1, 1, 6, -3, 6, -16, 1, 11, 12, 1, -4, 2, -9, 13, 4, 0, 4, -3, 3, 7, 1, -3, 6, -5, 11, 4, 13, -10, 0, 5, 0, 0, -9, 0, 2, 2, -1, -16, 11, 12, -8, -8, 3, -1, 6, -2, -7, -8, 18, 1, -14, 0, -4, 5, 12, 14, 3, 8, 4, -4, -3, 7, 15, -6, 7, 12, -2, -7, 12, -13, -16, -2, 10, -5, 1, 4, -5, 8, 6, 3, 11, 7, 0, 2, 0, 5, 8, 4, -3, 3, 8, 9, 12, -6, 8, 20, 6, 0, -12, 11, 10, -6, 3, 6, 1, 4, -4, -9, -10, -5, 25, -1, 9, -16, -3, 18, -4, -18, 1, -5, 22, 0, -3, -11, 13, 21, -4, -14, 15, -18, 11, -1, 12, 0, -12, 11, -4, -9, 19, -16, -5, 19, 21, -10, 1, -7, -4, -13, 8, 13, 17, 5, 4, -6, -12, 6, 2, 0, 13, 1, 25, -5, -27, -12, -7, 6, 5, 15, -13, 17, 32, 2, -14, -3, 11, 19, 8, 12, -41, 18, 8, -9, 10, 11, -1, -8, 7, 0, -27, 24, -26, -21, 21, 20, -20, -28, 8, 0, -3, 4, -31, 5, 4, -5, -10, -28, 10, 6, 0, -3, -53, 11, -12, -10, -2, -29, 12, 13, 4, -4, -35, 7, -8, -7, -1, -4, -1, 19, 2, -21, -27, 3, -1, 14, -8, 1, -14, -1, 1, -11, -3, -7, -2, 13, 6, -8, -5, -4, -8, -17, -4, 4, 20, 9, 0, -2, 2, 8, -14, -10, 17, -9, 19, 10, 23, -8, -11, 5, -11, -1, 18, 14, 2, -4, 11, -6, 13, -8, 2, 15, 8, 0, 13, 9, -7, 6, -4, -2, -16, 9, 0, -2, 4, 3, 6, -11, 7, -13, -7, -23, 24, 4, 3, -2, -2, -11, 1, 14, -5, -33, 18, -2, 3, 14, -10, -12, 3, 15, -18, -20, 12, -14, 1, 3, -3, -5, 4, -1, -6, -9, 32, -31, -4, 33, -5, -13, 10, 12, -14, 10, 23, -28, -11, 15, -6, -23, 11, 7, -17, 18, 11, -13, -12, 3, -12, -16, 1, -5, -23, 25, 13, -7, -1, -8, -9, -24, -14, -25, -13, 14, 10, 1, -5, -4, 2, -17, 13, -27, -32, 29, 12, -4, -8, -11, -5, -19, -6, 8, -16, 29, -25, 0, 22, 7, -4, 10, 3, 16, -29, 4, -28, -9, 17, 16, -20, 2, -1, 18, -12, 22, -23, -4, 25, 6, -14, 17, -4, -1, 8, 15, -37, -18, 24, 7, -18, 18, -11, -1, 18, 18, -15, -4, 26, -23, 4, 28, -14, -31, 13, -4, 2, 12, 10, -14, -1, 38, 7, -20, 18, -2, -4, 0, 10, -12, -3, 21, -1, -3, 30, -19, 6, 2, -6, -21, -2, 13, 5, -4, 20, -8, -4, 8, -14, -6, -17, 1, 3, -6, 20, -11, -2, 8, -15, -1, -4, -15, 2, -9, 29, 5, -22, 0, -14, 1, 2, -4, -8, 17, 25, -5, -2, -4, -20, 6, 6, -7, -18, 6, -1, -2, 6, 14, -18, 2, -11, 3, 4, 19, 11, -9, 15, 5, 0, -12, 3, 8, 8, 9, 5, -29, 7, 10, -12, 8, 1, 8, -7, 10, -2, -1, 0, 14, -6, 0, 12, 4, 2, -8, -7, -3, 1, -1, 6, 0, -9, 14, -3, -4, -5, 5, 1, 0, -9, 7, 1, 12, -11, -4, -3, 1, -3, 6, -4, 19, -1, 10, 1, -10, 0, -13, 2, -1, 8, -1, -1, 6, -13, 3, -1, -17, -6, 32, -2, 21, -12, 15, -20, -4, -4, -17, -15, 51, -4, -3, -7, 16, -5, -7, -19, 8, 8, 33, -10, -9, 5, 13, 5, 6, -23, 16, 4, 29, -1, -27, -14, 2, 6, 25, -3, 11, 11, -15, -8, -8, -26, -30, 23, 20, 3, 15, 6, -15, -2, 10, -14, -45, 16, -3, 8, 6, 0, -26, 24, 28, -25, -53, 19, -6, 21, 0, 5, -40, 26, 35, 11, -10, -4, -3, 13, -6, -14, -26, 10, 40, 22, 3, 15, 6, 9, -13, -7, -17, 1, 27, 13, -3, 10, -8, 10, -29, -17, -18, -5, 15, 28, 8, -4, 19, 4, -20, -8, -9, -16, -15, 23, 33, 0, 17, -13, -19, -14, -5, 4, -18, 26, 19, 0, 16, 13, 2, -7, -3, 24, -7, -1, 15, 9, -4, 13, 17, -24, -9, 9, -9, -20, -2, -4, -11, 2, 19, -14, 9, -1, 0, -14, 14, -10, -19, -5, 15, 1, 17, -7, 16, -12, 15, -10, -12, -10, -1, 4, 11, -1, 5, -4, 10, -8, -12, 0, -4, 5, 17, 1, -7, -20, 4, -5, 0, -2, 4, -2, -2, 14, -15, -3, 7, -1, -3, 7, 3, 2, -3, 6, -3, -2, -3, -2, -4, 2, 14, -4, -4, 4, -3, -2, -12, -9, -13, 9, 15, -23, -3, 16, -11, -21, -9, 8, -3, 1, 26, -16, -2, 19, 10, -16, 3, 3, 1, 0, 35, -11, -14, 23, 2, -13, -9, -1, -1, -15, 16, 20, -20, 10, 31, -3, -10, -4, 9, -24, -18, 30, 0, -7, 28, -3, -17, 13, 12, 2, -25, 13, 16, -18, 8, 26, -1, 3, 20, 21, -24, 24, 21, -8, 5, 20, 15, -10, 1, 2, -5, -7, 22, 6, -12, 9, 5, -2, 15, 16, 6, -16, 19, 4, 0, 3, 23, -12, 11, -13, 10, -11, 5, 18, -5, -20, 0, -7, 6, -1, 28, -27, 8, 0, 22, 4, -5, -14, -12, -16, 47, -9, 12, 6, 15, 10, 8, 5, -10, -27, 23, 12, -7, -36, -4, -1, -1, -14, -4, -16, 12, 28, 6, -27, -21, 10, -5, -1, 7, -20, -15, 24, 18, -32, -25, -5, -2, 5, -14, -1, -33, 5, 12, -2, -12, -9, -16, 9, 5, -13, -33, -9, 4, 9, 11, -16, -8, 14, 4, 12, -21, -14, -7, 14, 10, -9, 1, -4, -8, 10, -25, -5, -2, 15, -4, -19, 8, 9, 5, -4, -15, -11, -4, 13, -7, -18, 15, 12, 5, 1, -14, 13, -2, 20, -13, -12, 3, -9, -11, 15, -9, 3, 15, 13, -20, -14, -4, 7, -2, 3, 4, -5, 7, 7, -28, -14, -17, -2, 0, 17, -4, -5, 6, 0, -27, -15, -14, -3, -1, -16, 12, 5, 16, -11, 12, -4, -9, -4, 2, -4, -2, 0, -8, 1, 8, 5, -9, -15, 9, 3, 7, 12, -3, -5, 7, -9, 3, 7, 6, -8, 1, 13, 0, -6, 2, 1, 0, 10, 14, 4, 9, 4, -2, 1, 3, 15, 19, -16, 6, -1, -18, -9, -7, 11, 20, 10, 9, 8, -6, 12, -17, 3, -9, 15, 8, 11, 12, 1, 0, 8, -13, -13, 3, 1, -2, 2, 6, 5, 2, 18, -6, -8, 11, 14, 14, 17, 32, 4, -10, 6, 20, 22, -11, 5, -8, 13, 9, -14, -22, 10, 28, 2, -6, 5, 19, -6, 12, -22, -11, -15, 22, 12, 12, 11, 15, 4, 6, 0, -15, 0, 28, 10, -5, -3, 1, 3, 7, -11, -4, 16, 27, -18, -11, -15, 7, 3, 1, -21, 2, 18, -1, -8, 9, -27, -4, -24, 8, 4, -20, 12, -9, -8, 28, -3, -13, -37, -9, 14, -21, 10, -3, -10, 28, 17, -3, -26, -12, 9, 3, 21, -6, -14, 10, 12, 22, -25, -21, 8, -22, 27, 7, -41, -11, 7, 2, -4, 1, 1, -13, 26, 27, -33, -12, -8, -7, -6, 11, 7, 2, 23, 2, -30, -1, -6, 0, -14, 21, 11, -2, 14, 5, -22, 8, 7, -3, -5, 12, 3, 17, -7, 2, 4, -10, -10, -6, 5, -5, 6, 4, -8, 5, -2, 1, 0, -11, 7, 7, 14, 17, -22, 11, 12, 5, -2, -7, -3, 4, -7, 24, 2, -8, 3, 15, -8, -3, -1, -3, 10, 9, 9, -7, 2, 0, 7, -4, -10, 2, -10, 12, 6, 6, -18, 7, 4, 6, -4, 5, -7, 9, -4, 6, -10, -2, 11, 2, -13, 9, 3, 1, 10, 16, -4, 2, 4, 8, -5, 11, -13, -1, 2, 19, -10, -1, 3, 4, 6, 10, 5, -13, 6, 24, -9, -3, -2, -6, 1, -4, -14, 2, -10, -3, 6, -11, 3, 3, 6, 10, -5, -7, -11, 3, 6, -10, 4, -20, 14, 8, -2, -6, -18, 2, 33, -2, -16, -13, -12, 4, -13, -6, 6, -27, 23, -4, -23, -18, -4, 0, 5, 10, -10, -13, 5, -14, -24, 2, -7, 9, 12, 17, 9, -35, 0, 5, 4, -2, -23, 0, 9, 10, -15, -7, -6, 13, -1, -9, -13, 8, -6, -9, -20, 18, 30, 19, 5, -21, -16, 12, 13, -5, -34, 16, 30, 29, -14, -19, 0, -12, -8, -26, -14, 35, 36, 14, -15, -12, 3, -1, 12, -31, -34, 19, 19, 14, -7, 10, 5, 3, -6, -29, -16, 24, 20, -8, 8, 7, 9, 7, 4, -9, -1, 18, 1, 6, -3, 5, 1, 2, 15, 2, -2, 11, -17, -10, 14, 8, -7, 20, -3, -11, 0, -5, -10, 10, 7, 5, 7, 7, -3, -3, -5, -10, -6, 18, 14, -8, 6, 16, 1, 0, 5, -11, -16, -1, 5, 4, -18, 9, 4, 8, 13, 7, -15, 11, 7, 0, -3, 6, 7, 12, -31, -3, 12, 6, 7, -12, -5, 8, 7, -7, -9, -14, 15, -10, 11, -3, -7, -1, -14, -9, -3, -8, 15, -3, 4, -5, 12, -11, -12, -20, 18, -4, 20, -3, 11, -4, -9, -8, 4, -12, 26, -7, 12, -1, 24, 5, -6, -2, 8, -26, 37, -1, -25, -28, 18, 12, -6, -4, 12, -2, 20, 4, -23, -32, 4, 31, -6, -37, 19, -11, 21, 19, -24, -19, 9, 43, -30, -38, 18, 11, -20, 5, -30, -26, 22, 32, -25, -28, 8, 29, -29, 12, 9, -2, -10, 0, -20, -15, -14, 15, -16, -11, 33, -9, -42, -20, 5, -5, -8, 1, -6, 3, 16, -2, -32, -24, 21, 8, -3, 7, 7, 7, -1, -13, -9, -18, -1, 18, -9, 15, 1, 11, 10, -2, -7, -6, -8, -7, -7, -6, 5, 27, -4, -1, -3, 7, -13, 13, 1, 14, -5, 18, -4, 8, 1, 12, -3, 3, -2, 11, -12, 10, -6, 10, -1, 3, 5, 6, 11, 4, 8, 15, 2, 0, -7, -6, 4, 27, -15, 5, 2, 1, -4, 5, -22, -3, 2, 6, -6, -9, 11, -2, 9, 1, -1, -9, 7, 16, 6, -9, 9, -11, -3, 1, 0, -9, -13, 8, -4, 6, -3, 3, -7, 1, -1, 0, 17, -5, -3, -1, -14, -1, -8, 2, 7, -24, 4, 6, -9, 2, 0, -8, -11, 5, 4, 6, -8, -1, 9, -1, 9, 2, -1, 10, 1, 5, -9, 16, 1, -6, 2, 12, -21, -1, 10, 16, -1, 2, -2, 9, 12, 6, -17, 0, 5, -1, 2, 11, 10, 3, 23, 7, -15, 5, 3, -2, -5, -2, -16, -10, 18, 14, -25, -12, 16, 16, 7, -3, -15, -5, 4, 5, -20, 3, 7, 17, -12, 10, -14, 7, 0, -20, -7, 24, 18, -22, -17, 6, -1, 6, 5, -18, -5, 39, 0, -22, -20, 5, 2, -3, 5, -24, -16, 54, 7, -36, -1, 35, -13, 12, 3, -30, -11, 39, 0, -25, -6, 19, 12, 19, -16, -12, 1, 36, 6, -30, 12, 21, 8, 20, 3, -19, 13, 6, -10, -10, -4, 11, 14, 14, -6, 8, 11, -8, 9, 0, 6, 8, -2, -4, 3, 11, 25, -12, 6, -4, 4, 3, -13, -29, 10, 1, 20, -11, -9, -2, 26, 5, -9, -34, 14, -1, 23, -12, 13, 8, 29, 4, -7, -23, -11, -19, -1, -4, 15, 9, 7, 3, 14, -1, -5, -5, 7, 10, 15, 7, 19, -5, -9, -7, 1, 6, -7, -12, -9, 5, 16, -14, 4, 6, 11, 7, -14, -2, -26, -3, -4, -14, 3, 7, -5, 8, -6, -4, -21, -2, 0, -14, 12, 15, 8, -5, -1, -3, -12, -12, 11, -17, -4, 14, -7, -2, 12, 13, -21, 7, -6, -1, 16, 6, -36, -12, 2, 19, -10, -4, 2, -2, -1, -6, -20, 13, 15, 0, -3, 3, -12, -3, 5, -12, -18, 6, 11, 6, 4, 8, 6, 12, 15, 7, -2, -11, 10, 9, -8, -7, 12, -4, -10, 6, 0, 7, 5, 16, -6, -10, 20, 7, -10, 8, 2, 2, -6, 7, -5, 1, 13, -13, -9, -6, 5, 12, 2, 8, -9, 3, -4, 5, -4, -13, 5, -3, 12, 0, 7, 1, 0, 20, 4, -16, 12, -1, 16, 7, 5, -3, 11, 6, -9, -12, 15, -8, 12, 17, 8, 6, 5, 13, 6, -5, 6, -5, 15, 12, 19, 0, -3, 11, -1, -24, -1, 5, 13, 8, 19, -4, 13, 16, -19, -19, -2, 13, 11, -1, 14, -22, 13, 16, 3, -13, -12, 25, 18, -12, 1, -13, -3, 7, 3, 12, -13, -8, 4, -14, 1, 4, -9, -9, 5, 6, 3, -9, 13, -23, -4, 0, 6, 0, -12, -5, 16, 16, 3, -21, 15, 0, 4, 5, -5, -29, 16, 13, -2, -20, -7, 18, 19, 16, -18, -12, 0, -7, 6, -13, 4, 8, 30, 29, 6, -2, -10, -8, 13, 9, -18, -1, 40, 23, -4, 22, -19, -6, 0, 0, -25, 8, 32, 7, 13, 21, -16, 1, 6, 4, -14, 13, 17, 15, 6, 24, -14, 16, -16, 12, -14, 15, -4, 16, 8, -15, 1, 19, -21, 7, 20, -12, 5, 8, -1, 3, 0, 14, -35, 12, 12, 2, 14, 13, 17, 1, 8, -2, -25, 12, 21, 5, -5, 0, 15, -5, 4, 20, -25, 11, 17, -2, -9, -7, 5, -10, 1, 3, -7, 12, 1, 10, -15, -4, 7, 2, 7, 3, -29, 3, -4, -1, -14, 3, 0, -13, 0, 8, -11, -7, 7, 18, 5, 9, 7, 3, -28, -7, 17, -3, -10, 16, 6, 20, -7, -5, -19, -9, 8, 11, -2, 10, 5, 11, -4, 15, -11, 0, 4, -8, 8, -2, 30, 33, -4, 3, -8, -17, 19, -16, -10, -13, 15, 24, 11, -3, -7, -17, -6, -14, -3, -7, 10, 1, -17, -1, 2, -3, 4, 10, -7, -8, 16, 16, 2, 6, -9, -16, -1, 9, -9, -17, 8, 21, -9, -20, 9, -14, 3, 16, 9, 3, 6, 5, -12, -1, 10, 7, 14, 20, 9, -1, 4, -6, 10, -27, -7, 21, 21, 5, 6, 9, 2, -5, -2, -19, 12, 10, 16, 13, 3, 10, 5, -1, -12, -10, 7, 11, 1, 17, 10, 16, -7, -4, -10, 3, 18, 5, -12, 1, -13, -9, -11, -13, -12, 4, 11, 32, 2, 8, -40, -24, 0, -19, -15, 12, -10, 6, 16, 28, -33, -18, 8, -6, 1, 19, -25, 22, 22, 18, -29, -25, -6, 3, 7, -1, -13, 32, 31, -4, -5, -34, -5, -7, 4, 1, -8, 10, -4, -4, -9, -6, 10, -12, 10, 8, 20, -11, -27, -20, -17, 17, 31, 8, 20, 13, 20, -2, -39, -25, -20, 19, 16, 19, 18, 16, -2, -21, -25, -20, 3, 12, 22, 25, -1, 16, -2, -34, -16, 2, 6, 14, 24, 11, 2, -16, -14, -24, 3, 15, 31, -11, 17, 14, -8, 4, -3, 4, 0, 18, 0, -4, -5, 10, -2, -6, -1, 0, 13, 16, -2, -7, -8, 19, -13, 3, 4, 8, 22, 23, 3, -8, 2, 6, 3, -1, -1, 3, 4, 3, 0, 4, 1, 12, -8, -9, 15, 1, 22, 18, -11, 9, 12, 17, 6, -14, 5, 6, 20, 10, -6, 3, 6, 8, -12, -8, 16, 5, 18, -6, -4, 6, 6, 3, 0, -18, -11, 4, 14, -12, 4, 15, 4, -9, 3, -19, -25, -4, 33, -1, 17, 15, 16, 7, 6, -18, -25, -1, 3, -3, 26, 14, -1, -19, 4, -11, -24, -16, -11, 17, 17, 4, -2, -11, -2, -3, 0, 7, -21, -14, 35, 9, -4, -19, 4, -2, 3, 2, -33, -25, 27, 7, -7, -12, 0, 7, -4, 28, -16, -11, 4, 2, -9, -9, -15, 15, -10, 25, -4, -28, 14, 13, -24, 0, 3, 20, -9, 7, 5, -29, 12, -2, -19, -1, 13, 4, -2, 15, 7, 5, -3, -8, -23, -14, 4, 8, 20, 10, -17, 1, -24, -15, -9, -26, 16, 3, 26, 2, -39, -3, -12, 6, -22, -28, 14, -1, 13, 6, -19, 3, -19, -3, -10, -14, -12, 2, 14, -17, -18, -4, -22, 11, -17, 1, 2, 18, 0, -16, -5, 4, -3, 10, -5, -7, 5, 0, 7, -13, -9, -1, -6, -2, -3, 0, 6, 11, 5, -12, 16, 9, 4, -11, 4, 12, -8, 11, 3, -20, 18, 9, 0, -7, 6, -4, 19, 12, 36, 2, -28, -10, -55, -7, -33, -25, 7, 21, 39, 18, -35, -17, -42, -20, -28, -19, 16, 28, 0, 25, -28, -22, -31, -23, -30, -10, 12, 15, -5, 1, -17, -6, -2, 1, -21, -1, 12, -4, -24, -18, 6, 1, 29, 27, -29, -6, 10, -5, -19, -2, 1, 1, 25, 14, 3, 4, 5, -4, 11, -6, -3, -1, 7, 5, 3, 12, -15, 5, 21, -16, -11, -2, 1, 2, 22, 7, -18, -9, 24, -11, -16, -12, -9, 7, 14, -4, -15, -5, -1, -13, 13, 3, 19, 7, 4, -4, -5, -12, -5, -16, 15, 0, -9, -14, -2, -5, -3, 14, 2, -10, 22, -15, -16, -19, 9, 19, -8, 18, -19, -10, 7, -11, -16, -12, 4, -3, 6, 3, -13, -3, -2, 12, 20, -16, 2, -1, 12, -21, 8, 33, -11, 3, 22, -6, -11, 11, 6, -12, 7, 17, -31, -4, 21, 2, 4, 24, -7, -9, 16, 17, -17, 1, 1, -9, 15, 11, -1, -3, 5, 16, 0, 8, -1, 11, 5, 2, 11, 6, 4, 1, 0, 6, 2, 0, 0, 3, -7, -10, -4, 4, 6, 1, -6, -6, 8, 14, -10, -4, 2, -7, 15, -9, -2, -2, 10, -7, -12, -10, -9, 0, 3, 10, -21, 6, -6, -17, 0, 1, -20, 16, 8, -4, 11, -15, 0, 5, -13, 5, 3, -6, 6, -3, -5, 3, -4, 3, 5, -12, 10, 7, 10, -14, -4, 4, 11, -7, 12, 5, -23, -16, 13, -6, -1, -8, -6, -7, -12, -3, -16, -10, 13, -9, -3, 5, -8, -13, 3, 11, -16, 0, -10, -17, -2, 4, -9, -18, 6, -10, 7, -13, -6, -11, 4, -6, -14, -8, 9, -5, 10, -8, 1, -18, -17, 2, 3, -6, -13, -15, 17, -13, -7, -7, -18, 14, 1, 2, -22, 8, -11, -8, -6, -5, -4, -2, 8, 12, -13, 0, -1, 15, -16, 6, -10, 10, 6, 13, -2, -5, -7, -3, -10, -5, -1, -4, -13, 16, -11, -6, -3, 1, -15, 22, 33, -6, -25, 7, 12, 12, -2, 11, -4, 33, 19, -10, -30, 5, -4, -6, -20, -4, 33, 30, 13, -9, 4, -16, 10, 2, -3, -13, 33, 14, -7, -9, 17, -11, 13, 5, 14, -30, 9, -6, -23, 3, 18, 9, 10, 12, 19, -9, 13, -8, -34, -17, 21, 29, 10, 18, 19, 12, 1, 3, -11, -15, 0, 29, -2, 17, 0, 22, 14, 9, -14, -36, -11, 5, -4, -9, 4, 22, -1, -6, -19, -18, 4, 14, -5, 0, 9, 13, -11, -7, -11, -5, 17, 10, 7, -9, 18, -9, -14, 20, -25, 6, 3, 7, -12, 4, -15, 1, -15, 2, -7, -12, 17, -2, 8, 4, -14, 1, 3, -2, 1, 6, 8, 0, -3, 15, 2, -10, 9, 8, -13, -8, 2, 5, -4, -4, -14, 10, -1, -5, -6, -8, 15, 2, 13, -3, -13, -12, -2, 4, -16, -11, 7, 7, 4, 29, -5, 19, -13, -53, 0, 16, 0, -2, 12, 28, -13, 16, -13, -29, -5, -5, -4, 1, 18, -3, -10, 11, -6, -47, 5, 13, -12, -21, 17, -4, 13, 0, -23, -11, 9, 5, -11, -19, -2, 3, 13, -19, -19, -9, 13, -1, 5, -14, -21, -12, 7, -21, -17, -5, -14, 15, 19, 9, 7, -7, 15, -8, -18, -12, -21, 10, 21, 13, 2, 28, -10, -21, -5, -5, -5, 24, 16, 18, -3, 15, -25, -10, 3, 5, -1, 11, 10, 8, -5, 14, -27, 2, 3, 18, -1, 4, -5, 7, 5, -10, -19, 21, -13, 28, 15, -12, -4, -23, 4, -15, -3, 1, -26, 21, -10, -6, -1, -30, 7, -9, 25, -4, -37, 17, -20, 4, 14, 21, -12, -14, 17, -2, -26, 6, -36, -13, 2, 7, -6, -3, 2, 11, 14, -13, -17, 1, -6, 14, 8, -5, 6, -2, 11, -7, -13, 14, 0, 7, -13, -2, -11, -3, 4, 6, -13, 5, 3, 19, -9, -19, -3, 13, 0, 7, 2, -18, 5, 11, -2, -4, 6, 1, 6, 5, 7, -25, -4, 17, -1, 4, -16, 15, -16, 1, -4, -23, -14, 2, -2, -1, 4, -8, 2, 8, -3, -16, -13, 2, -4, -5, 6, -2, 8, 6, -2, 3, 3, -12, 1, 8, 5, -4, -5, -5, 4, 7, 2, 3, 14, 6, -11, -8, 12, -20, -10, 10, -16, 11, -10, 6, 8, -9, -9, -4, -1, -11, -9, 12, 10, 6, -13, 7, 25, -3, 11, 4, 4, 3, 6, -3, 2, -5, 5, -7, 5, 9, 28, 2, -10, 19, -7, -25, -4, -9, -13, -7, 33, 16, -4, 17, 16, -29, -4, -33, -33, -1, 40, 25, 12, 24, 16, -16, -11, -49, -20, 27, 35, 11, 15, 12, -27, -15, -26, -24, 14, 42, 4, 4, 10, -4, -36, -9, -14, 29, 52, 1, -21, -11, 0, -17, -23, 18, -6, 43, 20, -5, -19, -9, -1, -28, 14, 7, 9, 18, -2, -19, -6, 9, -6, -8, 9, 15, -2, 0, 6, -4, 9, 7, -5, -2, 14, -4, 2, 2, -7, 17, -6, 3, 0, 7, 4, 13, 9, 11, -4, 11, -17, 0, -11, 7, -3, 8, 2, -10, 15, 0, 3, -10, -15, -4, 2, 6, 15, 1, 15, 11, -10, -3, -3, -14, -5, 9, 4, 22, 11, -16, -6, -18, -6, -11, 28, -12, 14, 16, -19, -15, -11, -2, 8, -5, 35, -12, -19, 4, -3, -28, 12, -6, -5, -10, 28, 6, -34, 16, 2, -21, -5, 3, 5, 4, -14, 6, -41, -3, 14, -3, -16, 1, -5, -11, -21, 25, -27, 18, 12, -4, -20, -8, 4, -2, -31, 14, 3, 15, 4, 14, -2, -12, 13, 7, -24, 13, 0, 6, 9, 5, 0, -15, -10, 4, 1, -3, -3, 12, -12, -5, 10, -6, -4, 10, 3, -7, 5, -4, -8, -14, 1, -6, 4, 13, 9, -5, -3, 6, 2, -1, -11, 6, 7, 8, -21, -14, 6, 6, -9, 5, -12, -9, -9, 5, -25, -12, 20, 11, -17, -1, 2, -10, -16, 17, -27, -12, 8, 8, -13, 6, -5, 0, 10, 11, -1, -5, 14, 8, -17, 4, -14, -4, -11, -2, -3, -3, 12, 21, -13, -17, -4, 1, -2, 6, 16, -14, 21, 29, 4, -1, -12, 0, 15, 3, 3, -20, 14, 18, 18, -22, -3, -13, 0, -20, 15, -29, 15, 24, 18, 10, 4, 8, 16, -17, 2, -23, -3, 18, 26, 20, 5, -20, 6, -17, -8, -26, 16, 5, 9, 21, 14, 4, -9, -6, -28, -10, -1, 6, 14, 18, 8, -8, 13, -5, -17, 12, 4, -13, 0, 20, -11, 5, 11, 14, -15, 16, 27, -27, -20, 9, 2, 3, 12, 22, -11, 23, 21, -28, -15, 13, -4, -4, 10, 4, -26, 14, 17, -12, -8, -7, -4, -9, 6, -10, 3, 10, -16, -10, 8, -2, -4, -7, -9, -28, 20, 26, -29, 2, 6, 7, -20, 1, -7, -20, -1, 11, -42, 6, -9, -1, -13, -15, 7, -5, 11, 7, -14, 7, -11, 16, -6, -9, -3, 8, 14, 20, -10, -7, 2, 13, -13, -10, -21, -1, 11, 15, 2, -3, -5, 2, -10, 7, -6, 1, 15, 3, -21, -8, 4, 5, 14, -2, -12, -1, 12, 10, -20, 5, 0, -4, -3, 5, 5, 1, 11, 3, 3, 2, 11, -4, 19, 6, -6, 5, 6, 8, -6, 2, 8, -20, 4, 11, -1, -18, 0, -17, -18, 9, -4, 1, -7, 2, -15, -5, -3, 7, 6, 11, -3, 0, -2, 14, -7, -16, 2, 24, -10, 6, -5, 17, -6, 6, 9, -3, 22, 12, -28, -17, -6, 8, -9, -7, 5, 6, -1, 32, -3, -8, -37, 12, -1, -7, 9, 0, 10, 37, 18, -18, -10, 23, -8, -11, 9, 11, 6, 19, -2, -15, -26, 2, 4, -6, 6, 10, 19, 21, -12, -3, -11, 20, 8, 24, 8, 8, 3, 7, -23, -4, 15, 20, 4, 1, -14, 8, -3, -4, -22, 11, 6, 18, 16, 6, 11, 7, 14, 19, 5, 7, 3, 7, -3, 9, -6, -1, 4, 14, 11, 4, 11, 4, -11, 2, -10, 14, 19, 12, 16, 6, -5, 4, -9, -6, 6, -1, 12, 5, 1, 0, 1, -2, 4, -7, 4, 7, -5, -2, 3, -20, 1, -7, -3, 15, -17, -5, 7, 4, 12, -25, 1, -17, 18, 16, 1, -1, 12, -7, -18, -20, -13, -29, 7, 19, -2, -14, 10, 10, -2, -37, -27, -25, 8, 16, 2, -8, 13, 7, -29, -36, -42, -19, -3, 11, 7, 11, 18, 9, -21, -17, -29, 7, 3, 17, -11, 16, 3, -7, -33, -29, -15, 4, 4, -1, 14, -4, -21, 10, -22, -21, -9, 7, -8, -16, 12, 0, -22, -1, -7, -22, -2, 20, -17, -6, -3, 10, -11, -12, 1, -12, 8, 1, -18, -8, -4, -2, -5, -9, -7, -3, 0, -15, -12, -4, -10, -15, 15, 10, -9, 4, -6, 20, -1, 11, 2, 4, 5, 1, -15, 0, -5, 18, 2, -1, 0, 1, 15, -2, -24, 10, -27, 10, -4, 4, -11, 23, 6, 2, -14, -14, -42, 17, -8, -7, 7, 21, 15, -5, 1, -24, -35, 24, -10, -24, 6, 14, 12, 2, 13, -34, -23, 32, -20, -14, -10, 13, -16, -3, -6, -17, -18, 41, -11, -29, 14, -3, -19, 13, 5, -23, 31, 26, -34, -19, 5, -5, -12, 11, -9, 2, 36, 6, -19, -19, 2, -3, -16, 19, 1, 23, 24, -3, -7, -2, -20, -21, 1, -13, -9, 2, 6, -12, 1, 14, 5, 9, -2, -36, 3, 16, -5, -13, 17, 25, 2, 10, 6, -45, 7, 16, -2, -15, 20, 20, 0, 12, 5, -34, -13, -2, -10, -9, 1, 5, 13, 30, 16, -12, -12, -5, -2, 17, -7, -1, 15, 13, -12, -6, -19, 0, 31, 3, -21, 4, 11, -9, -3, 2, -2, 8, 36, 12, -10, 0, 1, -20, 1, 27, 20, 14, 24, 3, -12, 6, -2, -20, -11, 10, 30, 17, -1, -16, -20, 19, -1, -20, -8, 6, 29, 13, 11, -4, -4, 20, 5, -5, 4, 7, 21, 4, 10, 0, 14, 11, -6, -2, -6, 5, 10, -6, 2, -4, 10, 7, -3, -5, 14, -1, -7, -9, 11, -3, 7, -2, -10, 7, 7, -7, -16, -13, 6, -3, 12, 10, -8, -4, 6, 1, 0, -2, -7, -8, -4, -3, 3, 0, 7, 14, -16, -8, 1, -10, 8, -2, -1, -11, 2, 26, -20, -10, 4, -12, -6, 7, -15, 10, -11, -1, -13, 16, -10, 12, -8, 16, -11, 1, -8, -11, -2, 20, -12, 4, 2, 2, -2, 19, 1, -3, -9, 19, -30, 1, -18, 5, 2, 27, 3, -20, 7, 8, -31, -7, -8, -10, -7, 9, -2, -15, 22, 9, -21, 15, 6, -3, 3, -4, -4, 3, 29, 7, -28, 12, 3, -7, 1, 6, -15, -13, 31, -3, -28, -19, 15, -19, 7, 9, -12, -9, 23, -13, -18, -22, 21, -2, 7, 0, -21, 2, 20, -29, -24, -5, 31, 22, -5, 6, -26, 14, 15, -8, -5, 15, 30, 6, 4, -17, -23, 14, 3, 15, 20, -4, 20, 7, 12, -12, -19, 11, 18, 16, 21, -11, 0, 0, 14, -5, -4, 31, -16, 8, 1, 2, -7, -8, 20, 3, 9, 15, -1, -3, 2, 9, 2, -7, 4, -11, 20, 3, -19, -9, 11, 18, 2, -17, 4, -12, 20, 9, -14, -5, -2, 19, -7, -18, -10, -12, 18, -9, -8, -6, 13, 6, 8, -4, -2, -10, 7, -18, -19, 7, -7, 1, 14, -16, -9, -13, 0, 0, 1, 6, 12, 0, 3, 6, -14, -7, 7, 8, -6, 8, 15, 9, 7, -2, -14, 7, 19, -7, -5, 5, 5, 3, 0, 0, 0, 3, 7, 7, -7, -7, -1, 11, -1, -5, 4, 0, 12, -1, 4, 16, 4, 3, 3, 0, -6, 2, -11, -10, 5, 10, 6, -6, 5, 1, 6, 2, -5, -5, 4, 18, -2, -2, 17, -3, -11, -12, 10, 3, -5, 13, 7, -3, 23, -6, -5, -17, -6, 10, 9, 13, -6, 7, 11, -9, 4, 0, 5, 12, -6, 9, 8, -14, 25, 7, 7, -13, -21, 26, 12, 3, 15, -5, 3, -14, 7, -9, -10, 12, 17, -10, 12, 4, 2, 1, 9, -9, -19, 10, 13, -1, 2, 14, 4, 5, -5, 0, 0, -2, 6, -9, 0, 14, 2, 2, -10, 19, -2, -17, -7, 1, -16, 7, 13, 7, -13, 33, 1, -21, 3, 5, -36, -10, 3, 6, -14, 41, -1, -18, 19, 5, -47, -6, -8, 18, 0, 37, -4, -19, 34, -11, -24, -16, -7, -1, 14, 29, -13, -15, 36, -5, -32, -23, -20, 3, -2, 9, 2, -14, 0, 7, -2, 6, -19, 0, 16, -7, -2, -10, -11, 1, 8, 11, -5, 6, 11, -16, 11, 9, -24, 13, 10, 16, -21, 17, 1, -9, -4, 10, -29, 15, 8, 0, -7, 22, 0, -13, 8, 6, 1, -2, -5, 11, 5, 15, 3, -8, 0, -9, -5, 1, 7, -14, 2, 16, -8, -18, 3, -12, 1, 13, -5, 4, -1, 7, -12, -17, 18, -5, -4, -6, 2, -3, 0, 16, 6, -20, 10, 6, -15, -5, 30, 1, 1, 5, 11, -8, 5, 9, 2, 0, 10, -10, 6, -5, -3, 4, -8, 7, -3, 15, 9, -4, -1, 4, 6, -4, 2, -14, 13, 21, 3, -7, -6, 1, 9, 1, -3, 0, 6, 12, 2, -9, -4, -4, 2, 4, 5, 16, 20, 14, 1, 8, 5, 9, -5, -7, -25, 15, -1, -2, 1, 5, 1, 3, -6, -16, -20, 16, 9, 6, -11, 10, 20, 6, -12, 15, -38, 18, 21, -1, -10, -17, 8, 6, 13, 12, -30, 18, 15, -8, -20, -34, 6, -15, 20, 18, -5, 19, 13, -33, -23, -11, -2, -13, 5, 16, -20, 21, 1, -28, 3, 5, -3, -21, 15, -17, -24, 20, -14, -4, 31, 18, -9, -27, -1, -14, 5, -5, -23, 2, 35, 25, 9, -30, 6, -29, 18, -8, -33, 2, 3, 5, -6, 8, -7, -6, 14, -19, 1, -10, 7, -9, -1, 1, -10, -12, 12, -23, 11, -12, -1, 0, 2, 6, -18, -5, -17, -3, 25, 2, 23, 20, -13, -5, -10, -5, -14, -16, 8, 6, 30, 7, -4, 7, -7, 2, 1, -12, 6, 7, 3, -2, -15, -1, -3, -2, 16, 10, 7, 12, -2, -10, -4, 0, 4, 8, 24, 3, -12, 12, 17, -20, 1, -16, -6, -3, 3, 13, -4, 7, 8, 3, -22, 2, 15, 4, 13, 12, -1, 1, 10, 16, -13, 0, -3, 4, -14, 12, 0, -4, -7, 5, -9, 6, -6, 8, -12, -9, -5, 20, 0, 2, 6, 12, 4, 7, 4, -10, -5, 13, 7, -5, 7, 2, -8, 7, 7, -14, 0, 9, -2, -15, 10, 0, 2, -5, 1, 0, 2, -5, -3, 11, -5, 4, 3, -17, 11, -21, -4, -2, 19, 4, 9, 3, 3, -11, 26, -27, -19, -2, 14, 8, 13, 2, 14, -20, 28, -14, -21, -15, 25, -12, 6, -1, 9, -5, -2, -2, -5, -3, -1, 10, 3, 7, -19, 2, 13, 2, 14, 2, -8, 18, 8, 1, 11, 5, -14, -3, 12, 7, -13, -1, 1, -13, 16, 32, -16, -18, 15, 9, -17, -4, -6, -7, 2, 28, -2, 2, 5, -1, -25, -4, -5, -24, -4, 2, -1, 3, 31, 14, -28, -19, -1, -19, -10, 1, 4, 13, 5, 26, -21, -2, 14, -18, -12, 16, -6, -1, 1, 25, 1, 7, 2, -13, -4, 5, -13, -5, -19, 8, 1, 8, 6, -3, -7, -6, -9, 0, -8, 15, 3, 6, 12, -1, -7, 13, -13, -3, 3, 23, -15, 12, -13, -2, -10, 4, -4, -12, 16, 10, -19, 2, 13, 9, 3, -2, 7, 0, 9, -4, -5, -3, 15, -1, 7, -16, 3, -3, 20, 14, -17, 7, 11, 5, 1, -25, 24, 1, 7, -2, -3, -8, 14, -1, -13, -12, 22, 14, 3, -4, 11, 11, 17, 26, 3, -15, 9, -4, -9, 1, 16, 21, 13, -1, 3, 0, 3, 8, -16, -3, 1, -1, 3, 0, 7, 11, -12, 11, -9, 4, 3, 2, -21, 3, 7, -6, -5, -11, 5, -9, -10, -3, -7, -8, -3, 11, -32, -1, 1, 13, -14, 5, -18, 2, -1, 20, -12, -29, 9, -13, -8, 5, 5, -6, 7, 17, -11, -27, 1, 0, 5, -3, 4, 3, 9, -6, -2, -11, 5, -21, 19, 10, 2, -11, -6, -5, 7, 8, -5, -2, 12, 18, 11, -2, 5, -4, -4, 6, -2, 0, -1, 4, 14, -3, 4, -3, 1, 16, -4, 2, -12, 19, 5, -5, -14, 0, 0, 9, 23, -7, -14, -13, -4, 13, -8, 5, -18, -5, 47, 15, -25, -31, 7, 25, 11, -1, -22, -5, 35, 32, 1, -15, -22, 0, 1, 11, -47, -17, 36, 30, 4, -15, -36, -11, 14, 3, -13, -15, 4, 19, 16, 10, -12, -21, 16, 0, 21, 2, -24, -9, 1, 16, -5, -2, -6, -15, 30, 12, -22, -20, -17, 8, 25, 10, -14, 5, 0, 18, 2, -2, -29, -7, -6, 10, -15, -8, -4, -1, 25, 6, 3, -10, 10, -11, -4, -3, -26, -14, 32, 8, 14, 2, 8, -1, 5, -10, -10, -6, -2, -1, 33, 21, -8, -6, 20, -14, 10, -8, -2, -18, 24, -5, -6, 4, 1, 0, 21, 13, -8, -21, 13, -3, 7, -13, 5, 11, 17, 2, 5, -5, -4, -15, 2, -13, -11, -7, 5, 12, 9, 0, -5, 2, -1, -7, -5, 8, 7, 8, 2, -8, -13, 3, -12, -2, 7, -9, -6, 7, -5, 0, 7, -7, -6, -20, -13, 12, 7, 0, -7, -12, -15, 13, -8, -12, -6, -3, 4, 11, -21, 10, -7, 1, 1, -8, 4, 2, -1, 6, 7, 1, 13, 2, -6, 3, 0, -8, -7, -8, 14, 6, 12, 6, 5, 4, 2, -3, -2, -10, -2, 2, -1, 9, -1, 12, -4, -8, 3, -4, -4, -10, 5, 9, -5, 17, -12, -5, -16, -9, 3, 7, -2, 7, 7, 3, -9, -2, -8, 9, 2, 12, 8, 13, -4, -1, -10, 6, -19, 26, 4, 13, 12, 10, -1, -1, -21, 12, -10, 18, 8, 7, -5, 13, -7, -25, -11, 11, -3, 18, 13, 3, -26, -20, -10, -7, -8, 0, -22, 28, 22, 10, -31, -9, 1, 4, -9, 1, -14, -5, 28, 1, -21, -12, 21, 21, 13, 30, -15, -20, -17, 7, -25, 5, 35, -4, 12, 10, 13, -27, -32, 11, -6, 12, 15, -5, 8, 7, 2, 5, -28, -1, -3, 17, 21, 6, 11, 10, 15, 24, -14, -2, -14, 6, 11, -3, -4, -3, 15, 3, -24, -14, -16, -6, 10, 2, 8, 3, 24, 12, -25, -13, -14, -12, -13, 12, 12, -3, 3, 0, -3, -12, 9, -7, 7, 5, 11, -11, -6, 4, 8, 5, 33, -1, 1, -3, 3, -14, -2, -1, 4, 0, 41, 21, -7, -5, 6, -20, 9, -7, 12, -2, 20, 6, 7, -9, 2, -19, 6, 3, 10, -11, 23, 9, 4, 1, -8, -20, 16, -13, 5, -20, 10, 1, -2, 3, 3, 3, 11, -9, 13, -2, -1, -5, -10, -3, 3, -1, -3, -3, -5, -4, 4, 1, 12, 4, 2, 2, 15, 23, -18, -11, -2, 10, 5, -1, 6, -17, 9, 30, -17, -5, -12, 10, 0, 16, -8, 7, 7, 35, 0, -8, 4, 19, 4, 10, -13, -8, 8, 35, -2, -14, -2, 11, 12, 12, 1, -18, -3, 2, 2, 15, -14, -10, 6, 9, -12, -6, -17, -10, 13, 24, -15, 3, -10, 0, 6, -1, 6, -23, 6, 24, -17, -8, 1, 8, 7, 7, 0, -30, -7, 10, 1, -12, 2, 25, -8, 25, -5, -34, -2, 19, -1, -10, 2, 29, -5, 21, -14, -16, 18, 13, -16, -13, 20, 23, 7, -3, -21, -15, 46, 9, -5, -27, -2, 23, 13, 6, -26, -7, 24, 11, 15, -23, -10, 11, 7, 14, -13, -26, -4, 16, 31, 0, -16, -21, 12, 4, 22, -18, -25, 0, 17, 13, -16, -22, 12, 8, 36, -5, -13, -9, 12, 20, -15, -16, 0, -4, 37, 0, -16, -15, -1, 17, 9, -9, -4, -19, 0, -12, -6, -14, 4, 9, 5, 4, -16, -17, 4, -4, 5, 3, 13, 9, 1, -6, 2, -8, -17, -11, -6, -9, 5, 1, 4, 5, -12, -12, -12, -7, -3, 0, 17, -1, 16, 21, 0, 6, 1, 1, -6, -14, 14, 2, 3, 20, -6, 10, -8, -9, -16, -6, -7, -6, 4, 5, 16, 4, -2, -5, 3, -5, 0, -13, -6, 1, 6, 5, -8, 5, -9, 10, -2, 4, -12, -2, -7, 9, 8, -10, 2, 4, -4, -7, -2, 3, 6, 5, 20, -1, -10, -7, 9, 13, 14, 5, 15, -4, -4, 13, -15, -14, 14, 6, 0, -1, 3, -4, 10, 12, 0, -10, 10, 25, 15, 2, 7, -11, 3, 5, 0, -2, 16, 22, -2, -14, -2, 12, -2, -8, 9, 3, 0, 1, -13, 3, 7, 2, -2, -2, 21, 11, -3, 5, -1, 5, -14, 4, -10, 14, 20, 21, -16, 1, -8, 15, -16, 11, 7, 14, -3, 25, -13, -6, 2, 12, -14, 10, 0, 11, 5, 7, -5, 2, -18, 17, -6, -10, -8, 16, -26, -4, 6, -9, -20, 2, -7, -20, -11, 7, -12, -5, 23, -6, -20, -12, 8, -17, -25, 18, 10, -26, 26, 6, -34, -23, 7, -2, -15, -9, 29, -20, 2, 14, -9, -25, 1, 12, -8, -11, 30, -3, -8, 16, 14, 2, -10, 20, 1, -9, 9, -4, -1, 8, 21, 17, 1, 7, 8, -24, 20, -7, 7, 16, 18, 22, -9, 10, 9, -16, 17, 10, 5, -2, 19, 10, 9, 5, -13, -8, 10, 24, 18, -12, -9, 0, 6, -12, 11, -17, 13, 18, -2, 4, -20, 5, -4, -17, -6, -14, 2, 3, 12, 3, -1, 10, 10, -25, 4, -9, 11, 5, 2, 14, -8, 0, -2, -7, 3, 10, -15, -5, 1, 9, -3, 3, 12, -13, -6, 5, 14, 21, 7, -5, 11, 13, 3, 7, 9, -1, 0, -4, 10, 10, 10, 8, -12, -5, -9, 2, 5, 14, 3, 6, 18, -2, 3, -6, -9, 0, 1, -7, 1, 3, -5, 11, -7, -7, -2, 7, -3, -9, 20, 10, -3, 11, -3, -6, 7, -6, -2, -13, 3, 3, 3, 23, 0, -6, 4, 13, -9, -13, -10, 5, 9, 19, -10, 7, -15, 12, -18, 10, -14, -12, 3, 6, -3, 14, -27, 5, 6, 12, 1, -14, 9, 5, 10, 12, -23, -9, 10, 25, 1, -13, -18, -2, 21, 3, 5, -11, -15, 4, -5, -1, -7, -18, 11, 15, 19, -5, -21, -12, 7, -1, 5, -33, -9, -9, 33, 8, -5, -23, -18, 14, 18, 2, -17, -23, 21, 5, 14, -5, 10, -2, 2, 6, -15, -21, -8, 16, 2, 5, -8, -10, 19, -2, -3, -2, -28, -19, 20, 2, 8, -2, 1, -3, 6, 7, -21, -3, 5, 4, -7, 6, 12, 15, -1, 19, -5, -15, -6, 10, 1, -6, 22, 16, 6, 12, 11, 8, -9, -4, -20, -10, 18, -4, 0, -7, 9, 8, 3, 4, -32, 4, 11, -9, -9, 0, 10, 2, 17, -7, -17, -13, 5, -4, 0, -5, 7, 5, -4, -2, -19, 5, -6, -15, 18, 22, -8, 2, 10, 1, 11, -10, -13, -14, 9, 5, -3, -18, -6, 15, -8, 6, -23, -11, 6, 2, -11, -7, 11, 8, 22, -14, -8, 7, -8, 5, -4, 6, 3, -1, 12, 3, 5, 11, -11, -12, 4, -2, 17, 4, 11, 8, 9, -6, 3, -14, -10, 11, 6, 2, 27, 2, 2, 10, -2, -8, 0, 8, -4, -8, 11, -1, -3, 0, 3, -6, -6, 11, -16, 5, -1, 6, 9, 1, -8, -4, -8, 3, -5, -12, -11, 0, -2, 6, 5, 5, 7, 6, -11, -14, 12, -14, 13, 2, 6, 2, -1, 6, -8, 6, 6, 7, 5, 8, -6, -5, 8, 0, 4, -13, 4, -9, 4, -3, 0, 7, 10, 10, 7, -19, 1, -5, 6, 13, -13, -14, 23, -14, 27, 4, -1, -6, 10, -14, -15, -21, 23, -12, 11, -4, 22, 4, 24, -13, 5, -19, 21, -13, 5, 22, 3, 11, 10, -17, -1, -12, -10, -31, 11, 38, 12, -1, -5, -21, 17, 14, -13, -36, 34, 34, -3, -41, -1, -1, 15, 17, 5, -26, 25, 15, -18, -26, -4, 1, -4, 6, 2, -8, 44, -4, -19, -5, 3, -7, -8, -17, -4, -4, 32, -20, 7, -3, 22, -3, -2, -32, -11, 22, -14, -18, 20, 2, 9, 17, 2, -22, -7, 21, -32, -16, 14, 17, -5, 23, 8, 4, 12, 11, -12, -10, 2, 7, -6, 1, 9, 0, 7, -1, -14, 3, 0, -4, -2, -12, 14, -3, -9, -10, 11, -6, -4, 20, 2, -4, -6, 9, -9, 5, 3, -13, -13, 8, -7, -17, -4, 20, -4, 2, -6, -13, -4, 24, -3, -19, -14, 25, -7, 16, -6, -17, 1, 14, 6, -17, 0, 16, -1, -1, -13, 2, -5, 8, -1, -15, -2, 24, 3, 1, 0, -12, 3, 10, -3, 0, 8, 10, -11, 0, 14, 25, 3, 1, 3, -5, -4, 16, -11, 6, 11, 10, 0, 17, 11, 6, -7, 1, -11, 5, 1, 13, 6, 6, -4, -3, 0, -4, -12, -5, 15, 14, -10, 7, 14, -5, -4, 1, 9, 16, -13, 6, -17, -3, 4, -3, 5, 16, 19, 18, -5, -6, -31, -8, 1, 6, 12, 0, 17, 12, -15, -12, -3, -7, -5, -5, 3, 18, 6, 3, -24, -6, -11, 12, -9, -6, 3, -5, 4, -10, -1, 1, 16, 13, -21, -1, 3, 2, -15, -3, 16, 7, 33, 20, -39, -11, 15, -1, -27, -2, 23, 9, 29, 8, -31, 2, 12, -9, -5, -8, 2, -16, 15, 10, -11, 6, -14, -15, -7, 6, 12, -11, 31, 6, 1, 13, -14, -36, 7, 5, 16, 5, 36, 0, 9, 16, -14, -33, 13, 13, 29, -9, 21, 4, 0, 20, 1, -7, 9, 10, -3, -11, 24, 18, 7, -4, 4, -4, 5, 6, -15, -18, 7, -4, 4, -6, 18, 5, -3, -8, -11, -9, -9, 1, -15, 1, -5, 6, -9, 9, 5, 13, -4, -12, -15, -9, -20, -4, -18, 4, 12, 5, 4, -6, -10, -4, 9, 2, -10, 9, 21, 7, -7, -4, -1, -5, -12, -14, -16, 2, 9, 10, 3, 7, -2, 17, -7, -4, 1, 2, 0, 11, -2, 2, 5, 19, 7, -1, 5, 2, 6, 22, 9, 0, 12, 19, 2, 8, -8, 2, -7, 2, -13, 5, 8, 11, -1, -13, 7, -1, -3, -1, 6, -5, 5, -2, -10, 3, -3, 17, -3, 0, 5, 8, 1, 10, 2, 5, -7, -6, 12, 25, 1, 12, 1, 1, -8, -2, -16, -6, 0, 17, -16, 13, -17, -8, 13, 18, -3, -9, 2, 6, -6, 15, -3, -17, -6, 15, 5, 4, -2, 5, -15, 16, -8, -4, 0, 2, 4, -2, 4, 14, -22, 7, -1, 1, -15, -3, -3, 20, 8, 20, -21, -6, 7, -4, -10, -7, -30, 8, 9, 26, 1, 1, -6, 2, 18, 2, -4, 1, 9, 17, 7, 6, -28, -2, 7, 8, 24, -9, -51, 28, 10, 2, -22, -14, 17, 4, 28, 2, -68, 23, 13, -7, -11, -20, 5, -1, 2, 2, -39, 17, 18, -1, -20, 1, -1, -2, -22, 16, -21, 19, 31, 18, -9, 9, -4, -6, -31, 7, 11, 5, -3, -7, 14, 10, 6, -8, 1, -2, 13, -13, -5, -2, 17, -2, -13, 0, 9, 0, 2, -25, 3, -1, 17, 16, 12, -1, 19, -2, 1, -13, 10, 15, 14, -3, -10, -11, -5, 11, 13, -12, 8, -4, 17, -4, -9, -11, 17, -7, 25, -20, 10, 9, 6, 9, 8, -14, 7, -11, 13, 6, -18, -10, -9, 6, 1, -4, -4, -3, 16, -5, 4, -5, 7, 10, 1, 13, -11, -16, 13, 1, -11, 5, 9, 1, -11, -5, 8, 3, 14, 0, -1, 1, 12, -7, 7, -7, -8, 6, 13, 7, -11, 1, 10, 1, 10, 5, 1, 5, 1, -3, 8, 2, 8, -11, 9, -7, 11, 1, 9, 6, -18, -3, 5, -9, 0, -1, 18, 2, -10, -4, -11, -12, 7, 10, -9, 0, 9, 5, -10, -2, 2, -7, 5, 5, -9, 16, 13, -4, 2, -1, -2, 2, -1, 12, -9, 18, 5, 18, -7, 5, 9, 5, 5, 14, 3, 1, 9, 13, -2, 2, 1, -4, -6, 17, -12, 3, 4, 10, -2, 6, -15, -1, 1, 0, -9, -6, -8, 2, -4, 18, -10, -20, 14, -3, 9, -23, 2, 3, 14, 20, 20, -8, 13, 18, -7, -28, -16, 14, -10, 21, 11, -7, 9, 9, 3, -29, -9, 10, 10, 19, 38, -20, -20, 1, 5, -9, -28, 2, 15, 4, 44, 4, -23, 2, 11, -10, -38, -38, 24, -11, 26, 18, -9, -1, 16, 12, -7, -40, 18, -16, -19, 19, 7, -19, 3, 28, 1, -47, 6, -29, -43, 21, 21, -21, -5, 21, 12, -19, -9, -38, -29, 3, 11, -12, 9, 24, 2, -6, -23, -38, -34, 4, 1, -2, -13, 18, 5, 12, -14, -34, -14, 10, -15, -3, -3, 2, -5, 36, -16, -21, -4, 5, -11, -6, 12, -6, 5, 18, -16, -4, 9, 4, -19, -5, -3, 2, 4, 16, -11, -3, 12, 7, -13, 11, -8, -6, -15, 8, 6, 15, 13, 2, -6, 6, 2, 0, 0, 6, -5, 18, 3, 7, -19, 9, -2, -10, -15, -5, 6, 2, 9, 5, 11, 1, -12, -5, -4, 7, 9, 3, 6, -1, -4, 8, -9, 5, 4, -5, 10, -9, -8, -9, 15, 3, -10, -5, 9, 6, 8, -10, -6, -2, 9, 2, 9, 1, 26, -15, -21, 2, -2, 4, 11, 6, -3, -13, 41, -23, -35, 3, 14, 2, 19, -7, -5, 2, 20, -4, -49, -6, 36, 20, -1, 14, 10, -2, 21, -13, -26, 2, 35, 17, 7, 0, 16, -11, -20, 8, -27, 12, 26, 19, 3, -6, -8, 18, -24, 1, 19, 13, 13, -1, -8, -10, 11, 3, -43, 8, 51, 5, 7, -18, -22, -10, 3, 12, -42, 1, 33, 7, -10, -27, -27, -14, 12, -15, -31, 18, 38, 11, -10, -34, -23, 13, 1, -13, -8, 10, 9, 23, 2, -19, -11, -4, -9, -7, -19, 13, 8, 16, -7, -6, -4, 5, 3, -12, -15, 2, 8, 8, -19, 0, -14, 9, -9, -1, -18, 0, -10, 17, -23, 6, -6, 14, 5, 13, 1, -11, 5, 16, -8, -1, 0, 12, -11, 2, -7, -9, -4, 10, 13, -12, 0, 2, 2, 10, -10, -16, -5, 24, 5, -15, -3, 7, 6, 0, -10, 0, 8, 8, 17, -20, -7, 2, 0, 6, 7, -5, 6, -12, -4, -1, 7, -3, 3, -1, 9, 0, 10, 1, -1, 8, 4, 4, 8, -1, 8, -1, 12, 3, 6, -13, 8, 5, -5, -2, 13, 24, -9, -11, 1, 1, -11, 3, -3, 9, 0, 8, -4, -16, -11, -1, 0, -6, -10, 8, -9, 19, 0, 15, -4, 0, 2, 9, 4, -5, -2, 7, 5, 14, 9, 4, -6, 10, 11, 0, 5, 15, 1, -6, 6, 6, -5, -5, 4, 14, -4, -1, 3, -3, -1, 20, 7, 13, -5, 19, 3, -4, 4, -13, 1, 15, 11, 16, -10, 36, -30, 6, 22, -30, -7, 9, 30, -5, 9, 21, -29, 7, 20, -21, 12, 23, 22, -19, 9, -4, -31, 1, -8, -9, 17, 24, 12, -41, 18, -13, -13, 13, -34, -2, 14, 2, -12, -30, 11, -25, 18, 1, -47, 16, 5, -2, 4, -22, -11, -3, 30, -7, -28, 25, -30, -7, 6, 0, -16, -5, 16, -4, -5, 14, -36, 16, 5, -2, -8, -11, 14, -23, 5, 9, -22, 19, 4, 10, -13, -4, 6, -9, 7, 14, 2, -1, -11, 5, 6, -5, 1, -1, -6, -7, 9, 10, 2, 14, -17, 0, 16, 0, 6, 12, 20, 0, -22, 24, 0, -11, 16, 12, 1, 2, -2, 4, 2, 8, -9, -13, 21, -2, 25, -7, -5, 3, 3, 23, 2, 0, -1, 4, 11, 1, 8, 9, -8, 11, -13, -16, 4, -6, 10, 9, -4, 1, 10, 3, 14, -6, -4, 12, 4, -4, 7, -2, -5, 8, -4, -16, 1, 13, 0, 1, 10, -1, -1, -11, 10, 8, -22, 7, -8, 20, 4, -5, -10, -10, 13, -3, -9, -2, 9, 7, 3, 3, -7, -14, 4, 7, -5, -2, 18, 13, 4, -5, -6, -12, -7, -1, -9, -2, -3, 17, 0, -2, 3, 5, -13, -9, 0, 8, 7, 10, 0, -7, -3, -3, 2, -3, -14, 11, 5, 2, 6, -3, 9, 5, -4, -15, 5, 14, -9, 13, 9, -7, 5, 10, 4, -4, 8, 10, 10, 3, -7, -1, -1, 1, 2, 10, 17, 8, 6, 4, -15, -18, 5, -1, 1, 4, 1, -8, 12, -4, -15, 0, 25, -16, -7, 12, 8, 8, -7, -3, -19, 3, 0, -18, -19, -8, 5, 18, -1, 6, -14, -6, 12, -3, 2, -27, 8, 7, 20, 12, -18, -24, -9, 12, -12, 5, -16, 5, 19, 8, -11, -25, -16, 8, 8, 5, 4, -2, 11, -16, -13, 3, -10, -14, 21, 29, -8, -22, -29, -40, -6, 26, 0, -22, 21, 30, 9, -10, -50, -28, 8, 38, -14, -31, 12, 0, 3, -17, -44, -1, 15, 33, 4, -9, -15, 0, -23, 2, -17, 14, 29, 18, -6, 12, 2, -18, -5, -9, 0, 11, 11, 10, -9, 2, 4, -11, 1, -15, 23, -7, 4, -1, -2, 17, -14, -4, -13, -3, 9, 2, 4, -2, 12, 1, -1, -4, 2, -8, 10, 4, 10, 5, 7, -9, 8, -7, -1, -2, -2, -8, 0, -3, 1, -4, 6, 5, 5, -5, 2, -1, -5, -9, 14, 12, -9, 12, 6, 10, -11, -2, -5, 2, -2, 8, 1, 11, -6, -11, -10, 6, -2, -10, -8, 4, 11, 11, 4, -9, 13, 0, -8, 0, -3, -10, -1, 18, -4, -8, 0, -1, -18, -9, 4, 10, -11, 3, 12, -7, -8, -13, -9, -15, 3, -1, 9, -3, -1, 8, 8, -12, -12, 10, 9, 7, -3, 1, 0, -6, -12, -5, 19, 9, -4, -4, 12, 2, -16, -4, 4, 17, 3, 17, -3, -9, -1, -14, -1, -17, 13, -3, 8, -11, -15, -2, -5, -11, -7, 5, 8, 8, 18, -5, -9, 6, -11, -16, 0, -13, 22, 15, 7, -3, -4, -10, 5, -2, -5, -19, 26, 8, 10, -5, 16, 3, -6, -13, -5, -9, 1, 6, 23, 10, 6, -1, -11, 2, -5, -26, -2, -3, 29, 14, -9, 19, -8, -8, -6, -19, -1, 2, 36, 9, 13, 24, 6, 0, -16, 0, 4, -20, 12, 17, 5, 26, 2, 18, -7, 1, 8, -9, 23, 15, -3, -14, 7, 6, 0, -15, 24, 21, 3, 19, 15, -3, 17, 0, -1, -4, -4, 21, -2, 17, -6, -18, 15, 9, -4, 3, 4, 23, -34, -11, -5, -13, 8, 4, -4, 30, 11, 4, -48, -44, -15, 2, 10, -1, -7, 35, 0, 13, -46, -43, -21, -11, -15, -6, 6, 36, -6, 4, -34, -39, -8, 3, -11, -2, 10, 18, -10, 2, -13, -12, -22, -3, -3, -7, 7, 11, -20, 11, -4, -6, 2, -11, 0, 5, 3, 8, -22, -2, 9, 14, -14, 12, 3, 7, 10, 2, -7, -5, -5, 3, -14, 11, 0, -13, 2, 2, -4, 3, -5, -12, -11, -13, -1, -14, 0, -1, 5, -3, -3, 5, 15, 6, -12, -1, 13, -2, -5, 2, -3, 9, 14, -2, 6, 1, 2, 10, -19, 8, -5, 17, 2, 8, -10, 0, 18, 14, -14, 6, 10, -1, 1, -2, -2, -12, 3, 27, -21, 20, 20, 11, 0, 3, 8, -11, -25, 18, 0, 22, 31, 16, -21, -12, 3, -19, -50, 6, 6, 21, 19, -1, -27, -2, 14, -3, -53, -3, 13, 19, 11, -11, -20, -21, 16, 14, -38, -21, -5, -1, -10, -8, 5, -1, -10, 20, -9, -5, -19, 4, -4, 0, 0, -2, -17, 15, 11, 1, -23, 6, -16, -1, 1, 8, -1, 5, 31, 5, -33, 0, -10, -3, -7, -8, 4, 2, 33, -9, -40, 5, -14, 1, 0, -1, 0, 1, 38, -2, -28, 9, 9, -8, -10, -3, 8, -9, 6, -11, -1, 22, 14, -1, -27, -9, 3, 3, -12, -2, 16, 5, 16, -7, -23, -25, 13, 10, -16, -1, 43, 10, -1, -22, -5, -13, 3, 3, 4, -1, 42, -3, -11, -15, -19, -3, 7, 8, 5, -12, 35, -7, -13, -24, 1, -21, -2, -2, 6, -2, 18, -7, -11, -3, 0, -16, -7, -4, -5, 9, -2, 0, -14, -13, 6, 2, -10, -4, 0, 4, -1, -10, 0, 2, -9, -2, -7, 3, 3, -1, 2, 0, -2, 6, -1, 2, 9, -5, -5, 13, 6, -6, 1, -8, 1, -3, -7, -20, 1, -3, 11, 3, 14, -7, 16, 2, 1, -10, -9, 15, 4, -9, 8, 4, 1, 4, -6, -6, -3, -7, 5, -5, -2, -3, 13, 5, 3, -13, 5, 15, -16, -10, 1, -4, 9, 5, 4, -4, 0, -11, -11, 4, 4, 2, 8, -1, -1, 16, 8, -16, 1, -11, -6, -10, 14, 12, -12, 19, 4, -19, -1, -6, -14, -1, 0, 7, 0, 17, -12, -13, 5, 13, 0, 1, 13, 9, 8, 10, -22, -8, 14, 15, 22, 17, -6, 9, -3, -15, -13, 2, 1, -10, 21, 14, 0, 7, -14, 1, 8, 11, 8, 5, 9, -3, 22, 4, -12, -20, 20, 26, 9, -2, -4, -13, 1, 14, 7, -11, 32, 32, -17, -5, -20, 0, 3, -14, 5, 2, 40, 24, -34, -28, -19, -14, 3, -6, 14, 22, 27, 9, -37, -33, -29, -3, -21, -9, 10, 6, 17, 2, -19, -23, -23, 6, -10, 8, 1, 18, -14, -11, 6, 1, -4, 19, 13, -12, -14, 5, -8, -21, 17, 6, -4, 19, -1, -5, 6, 6, -14, -18, 1, 15, -16, 10, 2, 6, 19, 13, -4, -26, 11, 28, 9, -11, 8, 20, -7, -6, -13, -19, -7, 7, -1, 2, -3, 13, -13, -6, -7, 8, 3, 20, 19, 0, -7, 30, -1, -14, -16, 12, 0, 10, 13, 15, -9, 10, -8, -28, -3, 1, 5, 2, -1, 14, 0, 5, 4, -4, -9, -2, 19, 13, 10, 6, 2, -2, 10, -2, -2, -8, 5, 19, -11, 7, -8, -9, -3, 4, -1, -27, 19, -5, 7, -5, 4, 3, 12, -18, 20, -10, 7, 1, 13, -3, -3, 4, 15, -32, 16, -3, 14, -1, 25, -11, -3, 0, -1, -20, -3, -5, 6, -7, 32, -11, -33, 15, -1, -20, -2, -13, -10, -30, 34, 22, -29, -6, 24, -11, 3, -15, -3, -46, 36, 16, -31, 1, -2, 2, -5, -4, 22, -24, 6, 27, 9, -1, -9, 1, 1, -10, 11, -9, -20, 24, 25, -7, 12, 27, -10, -21, 25, -18, -35, 0, 30, -10, 15, 8, -17, -10, 16, 0, -36, -6, 17, -14, -15, 1, -12, 13, -3, 15, -25, 3, 3, 15, 6, 11, -10, 32, -5, 18, -18, -7, -14, -9, -17, 7, -30, 33, -2, 16, -5, 8, 1, 4, -14, -4, -24, 26, -13, 0, -6, 7, 10, 19, -15, 10, -2, 10, -17, 10, -12, 7, -4, 12, -9, 14, -3, 11, -23, 12, -8, 12, 2, 21, 5, 0, 18, 0, -15, 7, 2, 9, 8, 13, -8, 14, 6, -5, -5, -8, 4, 15, -8, 12, -4, -7, 16, -6, -2, 6, 1, 5, -2, 6, 6, -3, 7, -10, -12, 6, 14, -1, 2, -6, 11, -2, -8, 7, -4, 0, 27, 1, 1, 9, -7, -3, 10, 3, -1, 0, 8, -7, 0, 6, 4, 14, -4, 17, 0, -2, 8, -6, 6, 1, -5, -2, 19, 9, -2, -11, 9, -5, 5, -7, 0, 0, 12, 2, -4, 3, 8, -5, 4, 16, -5, -13, 3, -1, -10, 17, -4, -6, -6, 17, -2, -19, 8, 0, 15, 4, 21, -10, -4, 14, -6, -19, 16, -13, 14, 11, 17, 0, 4, -5, 15, -8, 26, -26, -12, 18, 5, 5, 2, 4, 19, -8, 12, -17, -17, 16, 5, -1, 0, -4, 2, 11, 6, -2, -11, 7, 4, 3, -3, 13, 1, -3, -24, 16, 9, 4, -3, -1, 13, -11, -1, -11, -15, 28, 3, 7, -7, -6, 7, 6, -8, 1, -2, 9, 6, -5, 6, -14, 15, -1, -4, -8, -3, 9, -4, 0, -6, 9, 0, 12, -11, -17, 4, -22, 17, 25, 0, 2, 16, -8, -3, 8, 9, -30, 4, 16, 2, 18, 3, -9, -8, 12, -1, -32, 21, 19, -8, 3, -1, -16, 3, 23, 12, -14, 29, -18, -6, 22, -10, -22, -7, 4, -5, 5, 31, -23, -8, 33, -27, -30, 1, 6, -21, 2, 55, -4, -10, 18, -29, -18, 10, 2, -30, -11, 44, -17, -3, 30, -18, -32, 11, 8, -20, -5, 19, -18, 10, 16, -25, -22, 8, -12, 2, 23, -10, -3, 1, 6, -29, -13, -12, 1, 8, 13, -12, -15, -7, 10, -10, -4, 9, 4, 4, 26, -17, -7, -7, -2, -11, -9, -7, -8, 10, 11, -1, -6, -4, 4, -18, 0, -2, 15, -9, 15, -18, -4, -11, 1, -6, 11, -9, 8, -16, -6, 1, 3, -3, 12, 9, 3, 9, 8, 0, -8, 1, -9, -15, 1, 12, 2, -2, -4, -3, -7, -2, -2, 13, -7, -6, -2, -8, 8, -3, 4, 4, 0, 9, 3, 10, -8, -12, 7, -7, 3, 7, -10, 6, 2, 1, -1, 5, 9, -22, 33, 13, 3, 8, 13, -7, 4, -13, -9, -15, 13, 14, 4, -11, 0, 13, 3, -3, 19, 9, 18, 0, 5, -19, -10, 7, -8, -4, -2, 34, 14, -20, 0, -34, 4, 7, 6, 9, -2, 25, 7, -30, 21, -13, 10, 12, 11, -4, -2, -5, 3, -25, 26, 17, 18, -14, -9, 6, -15, -19, 2, -17, 18, 17, -22, -19, -9, 5, -10, 2, 20, 5, 11, 20, -22, -6, -11, 5, -15, -4, -4, 18, 2, 13, -6, -1, -13, -14, -1, -2, -3, 7, 8, 15, -14, -15, 6, -5, 0, 17, -16, -2, -20, 22, -11, -9, -9, 0, 18, 2, -15, 4, -15, -6, -6, -11, -5, 0, 29, 3, -45, 11, -7, -23, 3, -31, -18, 24, 21, -3, -39, 37, -8, -8, 23, -24, -41, 10, 2, -18, -25, 36, -19, 4, 32, -23, -37, 0, -14, -19, -14, 26, -9, 6, 33, -20, -26, -2, -11, -27, 0, 22, -3, 5, 26, 6, -5, -6, -18, -7, 8, 13, 8, 8, 8, -7, 10, -4, -4, -8, 11, 0, 1, -3, 9, 1, 18, 7, -3, 15, 11, -13, 9, 5, 0, 10, 7, 4, -5, 2, 13, -5, -10, 5, 7, 7, 3, 6, -11, 5, 6, -11, 2, 25, -2, 8, -1, 10, -3, -11, 5, 1, -8, 14, 6, 11, -4, -6, -1, -2, -14, -9, 12, 5, 4, 12, 5, -1, -2, 17, -30, -3, 5, 3, -9, 13, 8, 1, 8, 12, -13, 3, 1, -1, -11, 5, 0, -5, 14, 31, -30, -31, 10, -4, -5, 0, 5, -3, -1, 19, -20, -33, -11, -14, 17, 14, 3, 4, 26, 6, -9, -39, 11, -6, 23, 5, 13, 18, 21, -3, -13, 4, 3, 25, 0, -10, 10, 7, 14, -9, 12, 5, 4, 15, -18, -16, -2, -8, -11, 3, 12, 45, 13, 41, -23, -6, -4, -6, -36, -4, 7, 39, 3, 23, -17, -6, 12, -4, -12, 5, -27, -3, 17, 32, 25, -12, -3, 21, 2, -4, -23, -11, -3, 29, 18, -6, -12, 9, -4, -12, -15, 1, 4, 7, -3, -11, 7, -8, 22, 3, 5, 14, 2, -22, -24, 1, 1, 1, 11, -26, 5, 36, 2, -40, -12, -2, 5, 8, -8, -14, 11, 34, 1, -29, -7, 4, -3, -18, 0, 2, 21, 5, -10, -8, -2, 1, 0, -8, -11, -1, 17, -13, -14, -7, 6, -5, 5, 4, -10, 5, 16, -7, -18, -16, 7, 22, 13, -7, 5, 4, 15, -9, -8, 3, 6, 6, 15, -2, 1, 13, 13, -9, -6, -5, 1, 4, 2, -2, -3, -6, -2, 0, -6, -7, -12, 8, 3, -7, 17, -5, -12, 2, -7, 5, -15, 4, 8, -2, -10, 3, -6, -5, 0, -2, -2, 14, -6, 5, -3, 6, 9, -10, -9, 16, -4, 16, -11, 6, 7, 8, 13, -16, -10, 8, 8, -6, 2, -4, -2, -10, -1, 10, -14, -17, -15, 1, 1, -10, 4, -2, 2, -8, -6, -7, -5, -8, 8, 4, -1, -5, 7, 12, -11, 14, -16, 3, 3, -11, 2, -6, 6, 27, -7, -1, -10, -9, -1, -2, -13, -26, -8, 33, -13, 15, 12, -19, 2, 7, -12, -21, -16, 19, -9, 36, 20, -32, -16, 9, -11, -11, -17, -1, 14, 29, 26, -36, -11, 10, -12, -5, 5, -20, 2, 20, 0, -22, 12, 14, -6, 15, -14, -19, 0, -4, 10, -32, 3, -1, 20, -10, -8, 9, 5, -28, -9, 0, -12, -12, 1, 0, 7, 25, 22, -31, 3, 16, 1, -16, 5, -22, -12, 28, 6, -32, -3, 17, 6, -9, 4, -19, 0, 27, 9, -29, -4, -2, -9, -3, 15, -18, -5, 19, 1, -18, 4, 9, -5, 16, 10, -3, -3, 16, 10, -12, 17, 10, 0, -9, -14, 7, 15, 4, -11, -7, 5, 8, -14, -13, -11, -12, 2, -1, -1, 0, 0, 18, 4, 3, -6, -1, 5, -2, 5, -2, -6, -6, -6, 13, 15, -6, 5, -6, 6, -17, -7, -3, -9, 5, 2, 3, 3, 7, 6, 0, -1, -6, 2, -11, -4, 16, -7, -8, -2, 3, 2, -1, 5, 8, 6, -2, 21, -7, 15, 8, 17, 10, -1, 6, -8, 17, 9, -9, -1, 1, 7, 10, 7, 3, 6, -10, 1, -16, 5, -14, 4, 0, 7, 0, -5, -11, 7, 5, 5, -17, -1, 10, 0, -4, 1, -14, 4, 8, 7, 1, 8, 16, -1, 12, -2, -12, 7, 4, -11, 4, -8, 8, 13, -16, -10, 3, 4, 14, 2, -4, 1, 11, 10, 2, -9, -7, 22, -6, -9, 1, 0, 6, 20, 2, 7, 0, 12, 4, -9, -1, 1, -4, -2, 4, 4, 1, 9, 2, -6, -8, -2, -10, 0, -8, -14, 7, 0, 3, -7, -6, 8, -2, 5, -17, 4, -18, 1, 6, 8, 8, 12, 1, -14, -3, -6, -11, -13, 7, 31, -10, 11, 2, -5, -12, 13, -1, -10, 2, 27, -20, 9, -14, -18, 0, 22, 35, 4, -5, 24, -28, -2, -18, -27, 4, -6, 34, 9, 1, 27, -18, -30, -15, -24, -10, -7, 26, 16, 12, 14, 12, -26, -23, 1, 12, -21, 17, -6, 29, -3, 1, -2, -15, -9, 15, -9, -5, -23, 20, -3, 15, 11, -14, 2, -2, 25, -6, -48, 7, -13, 18, 9, 3, 0, 2, 9, -2, -46, 16, 6, 11, 12, 6, 16, 2, 16, -15, -24, 25, 17, 8, 10, 7, 17, -3, -3, -18, -9, 17, 9, -6, 14, 12, 6, 15, 13, -13, -5, 18, -2, 3, 13, -5, -13, 11, 10, -26, 4, 11, -12, -6, 2, 3, 2, -11, -5, -3, 27, 3, -13, -11, 2, -13, -8, 9, -11, -1, 34, -11, 5, -5, 6, -5, -12, 17, 18, -11, 2, 4, -3, 3, 9, -24, -8, 15, 18, -19, -5, 4, 12, 17, -11, -1, -15, -2, 10, -15, -5, 15, 15, 12, 5, -7, -14, 3, 25, -14, -9, 12, 15, 22, 9, -4, -37, 15, 21, -18, -4, 6, 9, 9, 18, -11, -24, 20, 16, -15, 7, 6, 15, 5, 10, -8, -35, -7, 2, -2, -14, -8, 3, -23, -1, 11, -17, 10, 3, 24, 3, -36, 10, -38, 2, 33, -13, -1, 0, 26, 2, -34, -9, -26, -8, 29, 14, -11, 14, 10, 9, -16, -1, -17, -20, 30, 5, 3, 19, -7, 4, 2, 5, -23, -4, 12, 11, -10, -5, -19, 27, 16, 13, -3, 5, -6, 21, 1, -13, -14, 6, 15, 15, 10, 4, -13, 5, 0, -11, 3, 36, -3, -1, 11, 15, -5, 15, -5, -14, 10, 16, -5, -7, 6, 3, 4, 17, -5, -3, -7, -2, -3, -2, -2, 1, -10, 16, -11, -25, 4, 6, -5, -7, -7, 10, 13, -6, -4, -14, 6, -8, 7, -16, -1, -16, -6, -2, -5, -10, -7, 5, -4, 1, 5, -14, -1, 7, -3, -9, 2, 21, 9, -11, 12, 6, -2, 3, -11, -16, 1, 14, -7, 5, 18, 0, 5, 5, -6, -14, 6, 2, 4, 14, 9, -8, 16, 2, 3, -23, 9, -10, 13, 1, 8, -4, 18, 1, -11, 6, 1, 4, 12, 4, 16, 14, -14, 8, 11, -11, 6, -14, -2, 9, -3, 7, 6, 4, -5, -1, 9, 20, 2, -6, -8, 2, 5, 14, 7, -9, -8, 2, -2, -13, 2, -1, 12, 2, -4, 1, -5, 10, -4, 0, -3, 1, 7, -5, -4, -4, 6, 3, -1, 3, 7, -6, 3, 3, 2, -5, 4, 6, -4, -1, 15, -16, -4, 3, 3, -20, 7, 14, 3, 6, 21, -18, -6, -2, 0, -20, 19, 14, -22, 11, 31, -2, -27, -8, -11, -19, -4, 14, -5, 1, 30, 8, -37, -19, 9, -7, -1, -6, -4, 6, 14, 31, -20, -18, 16, 17, -15, -30, 18, 18, 7, 17, 2, -24, 16, 34, -10, -40, 39, 26, -11, 3, 3, -26, 1, 36, -11, -44, 15, 25, -29, 7, 31, -4, -14, 24, 12, -39, 6, 3, -18, -28, 16, 10, -2, 3, 17, -6, -9, -1, -19, -23, 14, 20, -11, 3, 11, 29, -20, -12, -1, -7, -9, 2, -7, -4, -3, 37, -9, -20, 1, 9, -24, 4, -12, -6, 6, 43, -9, -6, 1, 12, -18, -6, -5, -8, -2, 42, -9, -1, -2, 7, -14, -15, -4, -8, -8, 23, 2, 10, 9, 0, -19, -9, -2, -8, -15, 6, 15, 1, -4, 14, -14, -9, 9, 3, -3, -11, 15, -6, 4, 4, -12, 1, 12, -4, -15, -6, 14, 1, -1, 12, -6, -6, -6, -5, 2, -25, 7, 5, -11, -2, 7, 6, 11, 6, -9, -29, 0, -1, -9, -7, 1, 0, 3, 2, -8, -17, 7, -13, -3, 6, 12, -2, -3, 16, -2, 4, -8, -6, -20, -15, 8, 2, 1, 22, -5, -5, -1, -16, -8, -4, 3, 3, 14, 22, -30, -11, 24, -10, -23, -1, 4, 17, -10, 24, -21, -13, 17, -7, -12, -5, -8, 11, -3, 10, -29, 2, 18, -6, 4, -8, -12, -1, 16, -3, -6, -11, 2, 3, 12, -9, -35, -4, 16, -12, 38, -8, -16, -11, -6, -26, -11, 0, 11, -15, 34, 5, -4, -18, 0, -28, -10, 7, 5, -10, 10, 10, 8, -3, 2, -5, -15, -2, -1, -24, -14, -10, 32, -6, 24, 29, -11, -16, -6, -19, -25, -16, 27, -15, -3, 44, 22, -10, 5, 15, -10, -16, -11, -7, -10, 29, 30, -11, -4, 10, 12, -30, -2, 9, -15, 26, 35, -1, 3, 22, 1, -11, 0, 24, -20, 10, 39, -10, 2, 6, -12, -11, 19, 29, 4, 9, 28, -13, -7, -2, -4, -1, 11, 46, -7, 1, 28, -4, 2, 6, 3, -10, 12, 33, -2, -2, 16, -5, -18, -16, 1, -7, -1, 12, -2, 3, 10, 3, -4, -6, 13, 6, -16, 15, 3, -3, 19, 8, -3, -5, 11, 13, -9, -1, -2, 2, 6, 3, -6, -8, 10, 0, -20, -6, -9, -7, 1, -3, -7, 7, 11, 1, -6, -18, -2, -3, 0, -15, 7, 6, 23, 11, -14, -2, 0, 3, -6, -2, -8, -2, 11, 0, 4, 3, -8, -4, -6, -4, 6, -13, -2, -3, -16, 0, 6, -4, -1, 10, -8, -10, -16, -7, -3, 4, -4, 2, 2, 11, -9, -5, 9, -16, 6, 8, 11, -9, 16, 6, 2, -14, 17, -9, 5, 4, -2, -23, -5, -4, -3, -25, 43, 10, -6, 2, -8, -9, 9, 0, 6, -27, 38, 10, -32, 8, 7, -3, -6, 9, -1, -8, 21, 4, -20, -4, 5, -4, -11, 9, 13, 17, -11, 1, -2, -19, -5, 12, -5, 21, -11, 38, -25, -6, 9, -28, -24, 12, 25, 3, -13, 30, -36, -7, 25, -26, -20, 10, 18, 9, 9, 17, -30, -10, -9, -24, 8, 6, 26, 21, 19, 23, 1, -4, -38, -27, -4, 1, 9, 7, 12, 11, -4, 4, -41, -11, -3, -9, -7, 5, 8, -4, 12, -9, -11, -16, 5, -1, -17, 15, -1, -15, 2, -4, 3, -2, -7, 13, -19, -1, 7, -8, 1, -24, 9, 14, 0, 24, 13, 0, -5, -2, -3, -26, 3, 17, -14, 11, 28, 5, -10, -5, -1, -15, 0, 9, -10, 18, 19, 9, -3, 17, 5, -4, 19, 8, 2, -4, 4, 18, -7, -9, -7, 2, -4, 13, 13, 1, 6, 22, 0, 2, -4, -1, 8, 11, 5, 2, -2, -1, -2, 4, -9, 7, 3, 7, 14, -16, 8, 1, -5, 11, -13, 10, 0, 9, 13, -13, -3, 3, -4, -8, 7, 12, -4, 9, -5, 9, -7, 13, 11, -2, -2, 12, 7, 2, 2, 7, 7, 1, -2, -9, 9, 13, -14, 6, -6, 12, 6, -1, 3, -7, -2, -16, -9, 9, -3, 8, -23, 1, 3, -9, -7, 13, 5, 14, -6, -7, -22, -11, -1, -7, -6, 4, 22, 17, 5, -1, -23, 9, -1, 5, -4, 5, 11, 6, -4, -1, -6, -6, 3, -1, -17, 11, 5, 17, 3, 3, 2, 3, -12, -7, -7, 24, -12, 9, 11, 0, 10, 11, 5, -11, -18, 26, 12, 8, 16, -1, 21, 11, 2, -3, -11, 22, -11, 8, 27, 14, 15, 15, 2, -15, -3, 15, -18, 3, 53, 9, 9, 8, 9, -1, -22, 17, 9, -9, 44, 21, 15, 14, -8, 0, -9, -1, -6, -18, 16, 20, 18, 11, 10, -5, -14, 4, -26, -23, 7, 27, 19, 9, 14, 5, 8, -6, -20, -22, -11, 30, 21, -11, 0, 23, 0, -17, -2, -5, -14, 7, 32, 14, -11, 30, 6, -21, 14, 26, -18, -29, 22, 34, -7, 9, -3, -7, -14, 26, -8, -25, 24, 11, -2, 17, 11, -3, -18, 10, 5, -3, 0, 17, -9, 8, 9, 1, -3, 16, 21, 4, 0, 11, 3, -1, 2, 21, -15, 5, -1, -2, 6, 21, 4, -21, 10, 16, -3, 11, 6, 12, 3, 14, -14, -1, -8, 22, -9, 7, -2, 7, 2, 14, -4, -10, 6, 9, 9, 10, -2, -10, -7, 0, 7, -10, -2, 6, 15, -5, 5, -4, 5, 11, 7, -7, -8, -12, -10, 12, -1, -1, -12, 12, -1, -20, 3, -22, 19, 7, 5, -3, -12, 3, 8, -15, -9, -6, -15, 4, 10, 18, 2, -5, -2, 3, -1, 3, -18, -9, 20, 14, 0, -7, 0, -5, -26, -3, -19, -5, -7, -5, 25, 5, 7, -8, -8, 4, -24, 1, 5, 19, 15, 0, 1, 6, -8, -12, -20, 18, -13, -5, 22, 24, 3, 14, -1, -5, -21, 16, -14, -15, 6, 12, -10, 2, -2, 6, -9, 13, -9, -2, -13, 17, 10, 10, 27, 3, 10, -7, -2, -14, -18, 3, 6, 19, 27, 33, 5, -6, -11, 8, -4, -3, 4, 0, -1, 10, 27, -3, -7, -4, 6, -10, 9, 3, -9, 5, 46, -13, -9, 19, 27, -14, 8, 19, -8, -20, 29, -24, -14, 11, 20, -13, -1, 26, -8, -34, -20, 0, -18, 7, 28, 11, 0, 22, 22, -18, -24, 6, 9, -38, 10, 20, -10, 3, 9, -2, -7, 1, 0, -40, 8, 11, -1, -1, 13, 2, 4, -13, -16, -31, 3, 1, -14, -19, 14, 22, 5, -24, -10, -9, 6, 6, -19, -7, 2, -1, 21, -14, -5, -14, -3, 0, 1, -25, -2, -2, 24, -12, 3, -2, -2, -16, -11, -11, -13, 8, 8, 0, 26, -11, 2, -1, 11, -1, -12, -10, -5, 7, 23, -2, 13, -6, -6, -13, -10, -11, 7, -1, 6, 11, -6, 14, 11, -14, 2, -15, -5, 7, -2, -1, 12, 4, -9, -7, 0, -9, 0, 13, -1, 3, 7, 0, 9, 5, 0, 2, 5, -4, 9, -9, 8, 7, -6, -3, 3, 9, -23, -19, 19, 3, -19, 11, 18, -10, -12, 26, -22, -1, 29, 12, -1, -4, 4, -4, -15, 22, -1, -11, 22, 23, -15, -14, 16, 6, -1, -3, 17, -28, 5, 23, -7, -18, 5, 19, -2, -20, 33, 4, -23, 7, 2, -11, -1, 24, -6, -13, 22, 5, -23, 2, 10, 8, -18, 19, 1, -37, 16, 16, -10, -18, 8, 1, -19, 15, 6, -12, -12, 9, -10, -17, 2, 22, -10, 12, 19, 3, -17, -4, 8, -14, -19, 4, -13, 15, 9, 9, 11, 4, 4, -12, -17, -8, -11, 0, 5, 20, 27, 6, -6, 4, -15, -24, 4, -2, -2, 12, 22, -19, 14, 5, 6, -20, 7, -15, -2, 1, 3, -2, 10, -4, 28, 0, -6, -16, -7, 3, -16, 12, 21, -4, 27, -3, -10, -18, 13, 3, -24, -6, 22, -2, 15, -9, 10, -28, -6, 10, -17, 0, 19, 20, 2, 0, 12, -12, -2, -9, 21, -11, -14, 16, 8, -15, 11, -4, -20, -10, 24, -8, -16, 9, 31, 5, -1, 17, -18, -6, 14, 0, -37, -10, 19, -8, -3, 13, 4, 3, 3, -3, -24, -19, 11, 8, 12, 8, 8, -2, -12, 3, -25, -13, -9, 2, -6, 2, 7, 11, -2, 13, -17, -8, -12, 9, 1, -5, -2, 8, -16, 3, -21, -7, -16, 1, 12, -5, -12, -2, -5, 10, -16, 4, 5, -12, -5, -17, 4, 2, -4, 7, -2, 4, 4, -3, 8, -11, 7, 8, 0, 0, -10, 7, -11, -8, -15, 9, 12, -7, -22, 8, -10, -8, -7, -3, -9, -1, 3, -18, 1, -5, -15, -9, 0, 6, 5, -4, 8, -12, -3, -8, -6, -12, -6, 8, -13, -11, 13, 6, -9, -5, -12, -10, 0, -1, -5, -7, 13, -2, 8, -5, -4, -10, -11, 7, 10, 6, 8, -1, 5, 8, 13, -5, 16, 8, -5, -17, -18, -17, 33, 11, 12, -18, 10, 5, -4, 1, -51, -3, 40, 27, -2, -17, 16, 8, 13, -4, -39, 8, 43, 1, -12, -13, 35, -23, 10, 6, -31, -6, 10, -12, -14, -1, 22, -22, 17, 17, 2, 6, -11, -8, -31, 13, 36, -25, -13, 18, -2, -14, 11, -3, -25, -3, 28, -24, -9, 5, 11, -7, 24, 1, -11, -15, 13, 3, -9, 3, 14, -13, 4, 14, -5, -24, 1, 30, 10, 2, 23, -20, -11, 5, -12, -9, 9, 17, -5, 9, 6, -12, -13, -12, -13, -13, 4, 37, -12, 13, 18, -16, -10, -19, -14, -6, 9, 4, 2, 11, 4, 3, -6, -4, -10, -13, 8, 2, 3, -6, 7, 4, -4, -7, -9, -4, 5, 8, 11, 2, -8, 0, -2, -21, 6, 5, -6, 5, 2, -2, -23, 7, -19, -10, 5, 1, -3, -4, -6, 15, -21, 20, -17, -18, 8, 3, -5, -7, 9, 11, 1, 9, -15, -20, 10, -8, -11, -10, 13, -6, 12, 15, -28, -13, -8, 2, -4, 7, -2, 5, -3, -4, -10, 16, 12, -12, -15, 7, 3, -10, 23, -16, -6, 9, 6, 2, -4, 12, 0, 12, 13, -13, 3, 19, 4, 6, -11, 12, 0, 2, -1, -15, 12, 9, 22, 0, -4, -4, 3, 25, -3, 3, 1, 19, 6, -3, 5, 0, 4, -1, -4, 13, 17, 9, 28, -31, 3, 9, -2, 25, -10, 27, 15, -5, 6, -48, -15, 2, 10, 12, 12, 40, 4, -12, -1, -53, 24, 10, 10, 5, 19, 33, 13, -1, -22, -39, 36, -1, -1, 20, 5, 11, 11, 11, -33, -11, 9, -2, -6, 9, -11, -16, -8, 22, -25, -11, 1, -2, 6, -1, 18, -6, -9, 16, -20, -13, 9, -4, 5, 16, 7, -6, -5, -1, -36, -24, 12, -1, -3, -5, 12, -6, -27, 2, -25, -10, -7, -11, -6, 5, 11, -1, -6, -10, -14, -11, -26, 4, 7, -11, -12, 8, -18, -15, -18, -17, -24, 4, -5, -7, -18, 12, -10, -29, 12, 2, -31, -14, -7, -8, -8, -10, -7, -15, -3, 11, -22, -17, -5, -1, -25, -23, 1, -11, -21, 16, -7, 0, 1, 0, -14, -17, -6, -19, -8, 13, 4, -4, -4, 10, -3, -10, -7, -25, -22, 1, 8, -1, 7, -5, 4, -14, -17, 4, -7, -8, -1, -5, -7, -3, -8, 3, -7, -11, -1, 9, 12, 18, -6, -20, 2, 15, 3, 12, 7, -4, 7, -1, 6, -22, 7, 22, 2, 12, 2, -7, -4, 17, -8, 9, -27, -35, 24, 1, -10, 4, 11, 21, -5, 17, -17, -31, 32, 4, -7, -5, -5, 12, -7, 7, 4, -21, 25, 7, -11, -11, -30, -16, 13, 16, 4, -12, 9, -1, -5, 7, -41, -25, 20, 5, 30, -2, 2, -7, 4, 18, -44, -37, 20, -14, 7, 25, -33, 1, 28, 13, -32, -34, 3, -13, -10, 33, -16, 8, 38, 22, -15, -17, 9, -6, 6, 29, -13, -4, 21, -6, -16, -8, -15, 3, 15, 32, -6, -7, -4, -11, -8, 6, 4, 14, 9, 0, 3, 5, -11, -22, 12, 16, -13, 8, 8, -2, 6, -18, -5, -15, 22, 13, 8, -8, 1, -16, 9, -17, 20, 10, 1, -9, -3, -13, 5, -1, -4, -14, 19, 2, -19, 17, 7, -7, 10, 12, -10, -16, 14, -15, -10, 5, 3, -19, 16, -2, 2, -8, 4, 0, 2, 2, -14, -5, -9, 1, 6, -3, -1, 0, 16, 8, 10, -19, 4, -5, 2, 3, -3, -6, -2, 3, -14, -9, -11, 5, 0, 5, 5, -3, 15, 7, -11, 10, -11, 3, 12, 12, -18, -5, 10, 6, -12, -6, 6, 3, 7, -4, 1, -1, 4, -2, 5, 4, -8, 5, 2, 1, -8, -4, 4, -6, 7, 15, -7, -5, -5, -11, -7, 5, -10, 11, -11, 14, -18, 16, 0, -10, 0, 21, -4, -12, -1, 10, -11, 7, -11, 3, -7, 12, 1, -6, 8, -12, 10, 10, -10, -1, 0, -2, 4, -20, 9, -11, -4, 28, -11, 2, -2, -8, 5, 3, -5, 12, -9, 14, 2, 11, -6, 1, -10, -8, 9, -9, 2, 23, -9, -5, -2, 6, 8, -10, -6, -15, -16, 10, 0, 3, -10, 7, 7, 1, -8, 0, -9, -15, 17, -7, -3, 11, -9, -8, 8, -16, -8, -14, 13, 16, -14, 10, -7, -1, -16, -16, 0, -24, 8, 0, 4, 4, -4, 1, 6, -3, 12, -27, 11, -8, -2, 20, 3, -6, 3, -9, 4, -25, 4, -3, 1, 5, 3, -11, -12, 7, -1, -13, 1, 24, -7, 7, 13, 5, 12, 8, 3, -17, 6, -9, 27, 12, 10, -3, 6, 3, -28, 15, -4, 12, 27, 2, 5, -15, 7, -24, -15, 16, -10, -12, 28, 10, -7, -11, -8, -21, -2, 25, -9, 5, 13, 3, -3, -15, 6, 4, -12, 4, 0, -6, -10, 8, 6, -19, 13, 27, -6, -13, 6, 23, -31, -12, 27, -19, 0, 31, 7, -18, 13, 26, -30, 0, 21, 0, -11, 28, 9, -34, 19, 18, -25, -18, 37, 11, -7, 5, 12, -21, 0, 26, -10, -7, 19, 22, -9, -2, 21, -12, -7, 19, -10, -9, 10, 30, 4, 6, 5, 3, -11, 16, -8, 3, 5, 22, -8, -7, -3, -4, -12, 9, 1, -8, 1, 21, 0, -8, -3, -2, 1, -5, -9, 6, -8, -2, 4, -9, -11, -5, 2, 13, -11, 1, -12, 2, 4, 7, -6, -2, 3, 6, -2, -7, -18, 9, 5, 11, -13, -3, -12, -2, 2, 6, -9, 6, -6, 7, 1, 0, 2, 7, -6, 0, 4, -3, -1, -2, 5, 3, -4, 2, 2, 8, 6, -2, -7, 9, 3, 5, -6, 10, -6, 11, -11, 2, 3, -9, 11, 3, 9, 20, -9, -8, 6, 6, -13, 3, 5, 4, -4, 11, -17, -14, -9, -10, 6, -10, 38, 6, -42, 21, -9, -35, -3, 16, 12, -2, 44, 8, -65, 11, -14, -15, -2, 9, 7, 0, 7, 3, -71, 7, 6, -7, -2, 8, -5, 0, -14, 9, -36, 18, 15, 4, 1, -12, -6, 1, -33, 5, -2, -1, 26, 17, -13, 8, -13, 11, -39, -1, 40, -28, 11, 12, 4, 3, 8, 2, -40, -12, 25, -24, -6, 5, -8, -9, 13, 1, -6, -15, 10, -21, 16, 0, -45, -9, -4, -5, -10, -10, -6, 2, 34, -4, -36, -14, 6, 8, 5, -7, 4, 0, 17, 9, -11, 13, -11, -6, 3, 1, 17, 3, 12, -13, -1, 0, -18, -19, 16, 4, 7, 12, 9, -13, 3, 10, 7, -7, 5, -8, 4, -6, 10, -3, 11, -5, 7, 14, 1, -3, 9, 15, -11, -10, -8, 0, 12, -8, 23, -2, 3, 11, -8, -10, 0, 10, 4, 5, -1, 8, 8, 11, 5, 2, -2, 10, -5, 2, -8, -1, 6, -12, 5, 0, -3, 1, 0, -1, -1, 2, 9, 8, 5, 14, -6, 3, 0, -12, 3, 12, -6, -2, -2, 9, 9, -8, -3, 16, -9, 5, 4, -4, -3, 6, -9, -6, 3, -3, -29, 15, -5, -11, -12, -2, 3, -9, -6, -2, -18, 5, 10, -5, -9, 6, 2, 11, -5, 2, 3, -3, -5, -6, 7, 0, -2, 9, -2, -16, 2, -9, -17, -2, -11, 12, -17, 7, 6, -18, 3, 9, -15, 8, -1, -5, 6, 7, -11, -18, 14, 0, -6, -18, 6, -15, 8, -2, 6, -15, 26, -12, 9, -13, -5, -9, 6, 11, -12, -29, 24, 3, -1, -4, -35, -27, 10, 12, 7, -14, 37, 18, -6, -22, -14, -27, 5, 30, 8, -18, 35, 14, -22, -32, -13, -13, 7, 20, 11, -1, 27, 7, -23, -2, 6, 18, -5, -6, 13, -3, 10, -4, -31, 2, -5, 8, 14, -11, -6, 2, -14, -12, -14, 10, -13, -21, 14, 5, -7, 4, 18, 0, -7, -6, -13, -19, 7, 6, -10, 18, 20, -6, -14, -14, 8, -4, -7, 7, 2, -11, 17, 7, 7, 11, 1, -5, -8, -7, 10, 12, -17, 9, 27, -5, 9, 4, -24, -22, 4, 0, -4, 5, 24, 0, 16, 12, -18, -21, 9, 11, -19, 1, 30, 12, 10, 9, -23, -9, 8, 18, -28, -17, 37, 2, -6, 12, 7, -14, -11, 0, -18, 4, 10, -4, -16, 1, 10, -10, 5, 23, -22, 13, 2, -8, 2, 10, -12, 5, 0, 13, -2, 3, -14, -7, 2, 10, 8, 3, -11, 19, -14, 4, -15, -2, 3, 6, -11, 10, 17, -9, 3, 11, 21, -14, -1, 0, 13, -6, 5, -15, -10, -16, 15, -3, -2, -2, 12, 6, -4, -14, 1, -9, 14, -4, 5, -10, 9, -1, -11, 7, 13, -17, 7, -5, 8, 10, -3, -7, -8, -2, 1, -12, 19, 8, 5, -9, 11, 3, 14, -13, -4, -9, -10, 0, 1, 5, 12, -8, -4, -9, -9, 0, -6, 9, -9, -9, 15, 14, -13, -11, 4, -10, 0, 5, -16, -12, 4, -2, -11, -6, 6, 11, -17, 8, -11, 4, 4, -7, -14, 11, -4, 18, -3, 5, -6, 12, -8, -2, 6, 16, -6, 26, 9, 6, -2, 24, -10, 11, -12, 12, -3, -1, 22, 1, 2, 2, -22, -8, -8, 12, -1, -10, 45, -9, -10, 2, -19, -18, 16, 18, -9, -11, 36, -16, -1, 28, -14, -34, 18, -3, 0, -10, 32, -39, -3, 10, -13, -31, -5, 2, 16, 8, 8, -30, -7, -3, -6, -6, -3, 7, 19, -2, 7, -26, -9, -12, -31, -9, 5, 12, 4, 10, 0, 10, -2, -25, -42, 7, 4, -2, -17, 15, 3, 17, 13, -13, -46, -3, -8, 3, -2, 35, -13, 18, -7, -12, -43, 8, 11, 1, -3, 35, -23, 7, 12, 3, -23, -10, 7, 3, -2, 18, -6, 2, -3, -10, -3, -5, -6, -16, 9, 19, -25, -4, -1, -1, -7, -1, 13, 2, 12, 1, -22, -1, 0, -7, 3, 6, 2, -5, 17, -9, -10, -8, -8, -15, -9, 7, 1, 7, -5, 5, -8, -3, -2, -8, 6, 3, 7, 18, -9, 11, -2, 5, 3, -7, 4, 16, 10, 20, -2, 19, 2, 5, 14, 2, 4, 9, -8, -5, 7, 7, -12, 1, 3, -1, -7, -4, -11, 1, 4, 26, -15, 8, 13, -1, -3, -1, 0, -6, 6, 17, -18, 10, 0, -1, -1, 6, 4, 3, 15, 8, -7, 9, -9, -3, 2, 12, -7, 0, 9, 4, 3, -9, 0, -7, -2, 3, -12, -5, -1, 2, 8, 0, 8, -14, -2, 0, -14, 4, 3, 10, -6, -3, 2, -3, 9, 5, 9, 8, 3, 9, 7, 6, 7, -1, 0, 13, -8, -2, 17, -5, -18, -10, -16, -3, 18, -3, -12, -3, 16, -15, 21, -15, -26, -16, 16, 19, -17, -9, -20, -19, 46, 2, -35, -9, 5, 19, -5, 7, -38, -10, 37, 9, 5, 0, -22, -4, 25, 15, -40, -14, -7, 5, 24, 1, -42, -3, 26, 11, -28, -2, -30, 18, 40, -29, -17, 3, 15, 0, 14, 10, -30, 19, 23, -19, -24, -2, -13, -4, 10, -4, -16, 25, 9, -12, 0, 6, -2, -20, 23, -17, -3, 20, 5, -1, 10, 3, 2, -5, -5, -22, 11, 5, 8, 7, 12, 12, 0, -12, -1, -7, 13, -10, 18, -5, 15, 7, 13, -25, -1, -4, 13, -4, 18, 2, 15, 13, 9, 0, -20, 1, 12, -17, 15, -1, 14, -5, -10, -8, 5, 4, 2, -16, 11, 8, 3, -4, 8, 5, 5, -4, 1, -5, 0, -2, -1, 6, -6, -10, 21, 7, -2, -2, -5, 12, 2, 6, 4, -15, 16, 3, -9, -13, 1, -2, 5, 7, -14, 5, 20, 6, -14, 4, 3, -1, 1, 7, 2, 1, -5, 4, 0, -5, 0, -8, 4, 5, -15, -6, 4, 21, -5, 4, 12, -2, 1, 2, -1, -22, 1, 4, 7, 14, 4, 10, 1, -4, -19, -19, -17, 5, 18, 4, 8, -4, -4, 12, 13, -10, -17, -10, 25, 4, -4, -9, -20, -15, 13, 12, -4, -6, 6, -9, -7, 12, -18, -17, -5, -3, -7, -14, 10, -28, -2, 18, 11, 1, -12, -27, -2, -2, 10, -3, 5, 16, -1, -3, -18, -1, -20, 7, 9, 5, 12, 10, -4, -6, -17, 7, -4, 21, -7, 15, -3, 4, -9, -8, -2, -3, 16, 30, -5, 18, -15, -3, 2, 5, -8, -9, 16, 22, -17, 28, 7, -5, -10, -3, 13, -22, 7, 27, -12, 9, 3, -9, -23, -6, -2, -3, -16, 16, -4, 11, 19, -1, -16, 0, 5, -18, -3, -1, 18, 10, 8, 5, -21, -20, 3, 2, -17, -7, 22, 3, -1, -1, 7, -10, 8, 24, -14, -34, 31, 6, 1, -1, 16, -20, 13, 28, -3, -25, 22, -2, 1, 0, 12, -10, 22, 24, 1, -29, 17, 3, -10, 3, 14, -17, 17, 27, 1, -30, 6, -1, -17, 10, 1, -11, 1, 14, -16, -20, 3, 1, -16, -1, -1, -3, -7, 20, -4, 8, -6, 8, -5, 1, 5, 17, -9, 14, -9, 7, -10, 8, -1, 4, 5, 14, 10, 9, -18, 22, -2, -2, 9, 1, -9, 11, -10, 6, -6, -2, -3, 2, 0, 7, 5, 15, -2, -3, -10, 2, 20, -10, -4, 4, 12, 9, -6, -11, -4, 4, 13, -4, 9, -13, 12, 20, 4, -22, 8, -6, 24, -3, 5, -9, 0, 9, -16, -10, 3, 10, 6, 4, -15, -31, 5, 24, -5, 3, 56, -6, -15, -19, -21, 3, 17, 25, 7, 2, 52, 3, -57, -35, 5, 23, -7, 13, 1, 10, 8, 5, -33, -11, -4, 37, -11, -8, 11, -8, -10, 10, 8, -7, 7, 31, -25, -14, 3, -2, -32, 8, 28, 9, -2, 6, -16, -18, 0, -6, -25, 0, 40, 24, -3, -7, -14, 2, 11, -2, -25, -15, 43, 25, -12, -21, 2, 0, -1, -2, -18, -12, 44, 15, -15, -28, -2, 11, 6, 5, -19, -3, 36, 2, -3, -4, -2, -9, 11, -18, -9, 9, 26, -1, 7, 5, 0, -5, -10, -11, -18, 26, 2, 11, 17, 0, 1, -11, 0, -11, 2, 13, -2, -4, 5, 6, -5, -6, -1, -15, -9, 11, -8, -4, 4, -3, -6, -5, 13, -9, -5, 6, 7, 14, 5, 7, 4, -8, -7, 17, -12, -1, 4, 12, -8, -7, -3, -1, 0, 15, -11, 14, 6, 22, -15, 3, -4, -9, 1, 10, -8, -8, 14, 16, 1, -13, 2, -4, -3, 14, -4, 14, -2, 19, -4, 8, 0, 11, -4, 8, -7, 0, 3, 13, -4, -4, 5, -1, -11, -2, 3, 4, 7, 7, -16, -2, -13, -18, -17, 3, -5, 17, 9, 15, -24, -22, -24, -10, 16, 4, -5, 5, 21, 13, -5, -12, -1, -24, 16, -1, -22, 9, 25, 4, 2, 0, -14, -25, 9, 14, -22, -6, -12, -21, 14, 11, -5, 6, -2, 12, -4, -23, -22, -7, 1, 26, 27, 14, -7, 20, 13, -3, -26, -16, 6, 18, 9, -3, -11, 6, 22, -13, -19, -9, -17, 11, 12, -9, 12, 14, 12, -14, 0, -11, -16, -1, 9, 12, 13, 0, -1, -9, 25, 12, 5, -3, 1, 20, -13, -25, 6, 9, 19, 15, 23, 4, 20, -7, -18, -22, 9, 8, 9, 3, 18, 2, 0, 5, -16, -28, 7, 5, 22, -4, -4, -5, -2, -1, 7, 9, -2, 1, 0, -9, -27, -12, -2, 6, 5, 20, 8, 0, -2, -21, -41, -8, 7, 3, 20, 24, -20, 1, 1, -7, -1, 3, -2, -1, 3, -1, -25, -12, -3, 7, 12, 0, -11, -27, 8, -2, -18, 10, -11, 23, 16, 12, -15, -7, -14, -23, -7, -9, -14, 9, 10, -3, 10, 12, 4, -25, 15, 1, -2, 5, 7, -4, 16, 12, -7, -4, -6, -13, 8, 0, 0, -13, 12, 18, -5, -4, 11, -2, 5, -3, 9, -4, 1, 19, 11, -13, 4, -7, 3, -1, 0, 0, 8, 10, -9, 15, 0, 0, -17, 7, -11, 1, 6, 12, -5, 2, 9, 4, 1, 10, -11, 4, -4, 6, 10, 12, 24, -6, -11, -1, 6, 9, -8, -11, 4, 7, 4, -3, -3, -1, -11, 13, 12, -10, -2, -8, -7, -3, -10, 6, -1, 9, 19, 3, 16, 6, 15, -14, 0, 8, 0, -9, 21, 10, 13, 12, 5, -3, -16, -7, 21, 2, 15, 8, -6, -7, 6, -13, -10, -13, -1, 5, -8, -5, -8, -14, 6, 7, 1, 12, 21, -1, -1, -25, 6, -16, 7, 15, -15, 14, 24, -12, -19, -7, 23, -1, -2, 3, -18, -3, 1, -9, -6, -7, 17, 15, 15, -1, -8, -1, -25, -14, -9, -35, 12, 28, 5, -13, 27, 19, -31, -28, -19, -21, -6, 15, -7, -18, 41, 22, -41, -37, -4, -14, -9, 12, -12, -19, 38, 8, -43, -23, 11, -10, -12, 3, -17, -17, 25, 8, -3, -4, 12, -5, -9, -14, -15, -2, 15, 8, 7, -16, 9, 9, -8, -13, -1, 16, 6, 6, 9, 6, -3, 10, 4, -21, -6, 13, -3, 1, -4, 18, -6, 0, -8, 3, -7, 25, -9, -6, -1, -1, 4, -2, 2, -11, -11, 2, -8, 4, -3, 5, 4, -11, -12, -12, -3, 11, -18, -3, 11, -2, 9, 13, -14, -16, -1, -1, 9, -6, 6, -1, 5, -4, 13, -15, 2, -2, -4, -4, 14, 6, 3, -17, -5, -3, 7, 7, -1, -1, 6, 4, 4, -3, 2, 8, 7, 18, -15, 9, 3, -14, 3, -13, -7, -4, -15, 23, 2, 0, -9, 7, 8, -8, -19, -3, -10, -9, 14, 8, -7, -9, -7, 10, -10, -5, -17, 0, 6, 20, 15, 18, -9, 2, -15, 15, -6, -28, -5, -2, 8, 1, 10, -1, 7, -1, 0, -15, 18, -5, 8, 2, -6, 9, -1, 18, 3, -8, 14, -20, -1, 6, 6, 6, -5, 13, 11, -7, 7, -18, -6, 16, 7, 22, 0, 14, -9, 4, -5, -8, 16, 20, 1, 15, 16, 4, -24, 28, -15, 8, 32, 8, 1, 12, 18, -11, -21, 33, -9, 0, 31, -12, -22, -11, 0, -11, 12, 26, -6, -2, -4, -31, -12, 6, -14, 15, 37, 18, -30, -7, -33, -25, -9, 16, 13, 4, 44, -5, -34, -18, -18, 4, 11, 10, 14, -7, 0, 18, -36, 23, 12, -4, -16, 3, 4, -8, -13, 25, -3, 16, 5, -19, -12, 5, -7, -17, -8, 18, 6, -4, 2, -24, 0, -11, 9, -2, 21, 22, 6, -24, -6, 6, -4, 6, -7, -15, 20, -5, 5, -29, -11, -4, 8, -7, -7, -10, 16, -18, 4, -22, -2, -4, -3, -7, -6, -15, 27, -14, 3, -22, 7, -15, 6, -10, -9, 6, 4, -7, 10, -18, -8, -9, -2, 9, 12, -5, 4, -10, 7, -23, 3, -8, -6, 5, -1, -10, -1, -12, -8, 6, -4, -1, 3, -4, 13, 6, -6, -14, 14, -2, -10, 5, 13, -3, 7, 0, -7, 0, 9, -22, 6, -10, 6, 1, 7, 8, -24, 3, 4, -10, 2, -3, 9, -14, -1, -1, -16, 5, -12, 5, 14, 3, 17, -9, 8, -11, 6, 15, -16, -3, 12, -3, -7, 3, 0, -19, 22, 4, -21, -9, -9, 3, -3, -2, -2, -9, 13, -7, -8, 6, -10, -7, -5, 13, -2, -9, 16, -15, 11, 2, -3, -1, -10, -6, -10, -2, -2, -15, 8, -8, -1, -8, 0, -6, -2, -23, 1, -6, 5, -1, 0, -3, -7, -6, 10, 1, 12, -4, 12, -1, -2, -14, 12, 8, -12, 0, 11, -5, -4, 1, -8, 10, 4, 0, -10, 4, -12, 9, 7, 15, -1, 8, 3, 12, -12, 9, 3, 12, -5, 1, -8, 4, -9, 18, -16, 22, 9, 6, 8, -5, -26, -2, 21, 27, -20, 34, -29, 2, 25, -14, -33, 2, 31, 15, 4, 18, -27, 4, 44, -3, -1, 20, 10, 10, 11, 2, -43, 20, 13, 8, 32, 15, -11, -17, 11, -4, -9, 25, -33, -2, 46, 6, -8, -13, 16, -12, 3, 15, -58, 1, 16, 1, 4, -20, 12, -21, 27, 6, -44, 3, -15, -4, 8, 6, -10, -1, 11, -7, -27, 10, -25, -1, 9, 10, 4, 6, 15, 1, -8, -5, -24, -9, 2, 6, -3, 10, 16, 1, 3, -5, -29, -22, 2, 5, 7, -5, 21, 8, -15, -9, -9, -9, -22, 11, 7, 2, 9, 6, -5, -9, 6, -24, 0, 0, -4, 8, -21, -4, -21, -16, 8, -4, -7, 8, 17, -17, -15, 8, -24, 12, -1, -3, -13, -7, -1, -3, -31, -6, -24, 19, 16, -9, 2, -8, -15, -16, -9, -2, -10, 10, 5, -14, -11, -8, 3, -18, 0, 5, -6, 15, 4, -13, -11, 8, -8, -6, 27, -13, -7, 10, -21, -6, 14, 32, -17, 3, 32, -34, -10, -8, -25, 9, 24, 14, -3, 19, 20, -36, -2, -14, -3, 14, 20, 15, 17, 29, 9, -34, -15, -27, 11, 28, -8, -1, 20, 21, -10, -8, -8, -13, 39, 33, -24, -14, 4, 12, 2, 5, 3, 6, 16, 10, -2, -25, -4, -20, 4, 34, -3, 4, 11, 3, -14, -20, 10, -12, 13, 18, 11, -14, 9, 11, -9, -4, -9, -16, 9, 16, 1, 21, 7, -7, 2, -7, 0, -11, 3, 2, 15, 14, 11, 5, -4, -7, -7, -20, -6, 2, -5, 9, 13, 17, -10, -8, 0, 10, 0, 17, 8, 11, 17, 11, 7, 12, -21, -9, 3, 12, 5, 9, -14, -2, 1, 5, -2, 6, 16, 9, 9, -6, -18, -9, 6, 7, 11, 3, 22, 13, 12, 3, -10, -13, 5, -3, 0, 14, -5, -14, -5, -2, -12, -9, -6, -13, 1, 16, 4, -1, -6, 16, -1, -17, -8, -15, 0, 9, -4, 6, -5, -1, 0, -4, -14, 9, 9, 17, -10, -12, -18, -6, 4, -9, 0, 2, 2, -5, -10, 2, -3, -4, 9, -9, 2, -3, 3, 3, 2, 2, 19, 0, 0, -7, -5, -6, 9, 14, -11, 4, 22, -10, 13, 4, -14, 1, -9, 1, -7, -1, 9, 7, 3, 5, -15, 11, -3, 3, -9, 8, 23, 1, 20, -8, 10, -7, 2, -13, -7, -1, 13, 12, 4, -7, 0, -1, -16, -16, -4, 3, 22, 11, 15, 6, 10, 8, -2, 5, 10, -5, 17, 0, 20, 4, 5, 11, -2, -3, -5, 2, 12, 5, 17, 7, 5, 4, -16, -2, 11, -4, 25, 4, 8, 20, 5, 9, 4, 3, 4, 19, 22, 13, 10, 3, 8, 5, -9, -10, 9, 9, 20, -7, -12, -2, 9, 13, -2, -4, 21, 9, 1, 14, -22, 13, 20, 1, 6, -16, 16, 8, -31, 23, -1, 9, -6, -2, -12, -16, 8, 7, -31, 15, 15, -16, 0, -1, 12, -20, 7, 9, -6, 10, 2, -15, -12, 18, 8, -1, -20, 3, 16, -5, 0, 4, 3, 21, -14, 6, -31, -10, 12, -23, -12, 14, 3, 6, 4, -5, -44, -4, 13, -30, 12, 15, 6, 4, 6, 0, -35, 11, -24, -29, 25, 22, -1, -15, 8, 19, -12, 9, -46, -39, 11, 22, -12, -8, 5, 19, 10, 15, -65, -42, -11, 20, -18, -13, 14, 17, 42, 4, -54, -26, -12, -2, -6, -2, 11, -1, 33, -17, -38, -13, 5, -8, -23, 14, -1, 17, 5, -5, -17, 3, -2, 4, -9, 6, -2, -5, 15, -15, -20, 30, -5, 4, -18, 3, -9, -8, 10, -7, -9, 2, -5, -10, -2, 7, -1, 3, 6, 3, 4, -11, 1, -7, -9, 17, -10, -17, 13, 10, 17, -7, 10, -2, 0, 8, 8, -12, 3, 13, -8, -1, -1, 15, -23, 10, 3, -10, 2, 8, 9, 0, 2, 8, -1, -1, 10, 11, 8, -5, -11, -11, 2, -4, -11, 1, 1, 10, -3, 0, -6, -9, -13, -3, 15, 6, 6, -11, 3, -9, 9, 3, 3, -4, 5, 4, -9, -1, 0, -6, 7, -15, 7, 4, 9, 3, -11, -12, -11, 24, -2, 4, 8, 8, 8, 2, -8, -23, -1, 25, -14, 1, 14, 27, -9, 7, -3, -7, -21, 20, -2, 24, 6, 10, 3, -10, 6, -4, -35, 8, 23, 25, -5, -17, -7, -17, 18, 8, -31, 5, 3, 16, -17, -16, -7, -4, -4, -3, -18, 7, 2, 18, 0, 3, 4, -17, -5, -6, -15, 6, -2, -10, 5, -16, 17, -24, -15, -15, -2, -9, -6, -8, 25, 1, 13, 7, 10, -22, 11, -5, 3, -15, 45, 24, -8, -5, -1, -11, -4, -11, 16, -19, 23, 21, 1, -8, 16, 19, 0, -36, -5, -3, -9, 30, 17, -20, 19, 27, -12, -31, 16, -1, -14, 0, 7, -2, -4, 28, -6, -24, 4, 0, -17, 6, -13, -9, 9, 20, 6, -3, -5, 14, -16, -21, -7, -10, -12, 18, 3, 10, -1, 1, -13, -21, -3, 6, -3, 2, 17, 12, 12, -4, -22, -15, 3, -4, 6, 15, 12, 9, -17, 2, -8, -4, -6, -4, 1, -7, -4, 4, 6, -12, 4, 5, 14, -7, -5, -12, 8, 6, -4, 10, -5, -4, 0, 4, -3, 6, -8, 3, 13, -3, 14, 11, 19, 4, 5, 0, -2, 2, 32, 10, 12, -7, 15, -6, -6, 8, -15, 4, 15, 22, 4, -8, 10, -3, 6, 18, 13, -2, 20, -10, -4, -10, 21, -6, -18, 12, 10, 13, 4, -17, -22, 3, 25, -22, 6, 12, 20, -2, -12, -34, -7, 13, -4, -21, 2, 8, 1, 0, -7, -8, 4, 25, -26, -12, 1, -20, -18, -6, 21, 9, -3, -4, -14, -6, 8, 4, -3, -12, 7, 21, -10, -3, -4, 28, -2, -1, 6, -27, -6, 20, -16, -11, -4, 26, -17, -14, 0, -14, -4, 12, 11, 1, -13, 26, -16, -7, 8, -3, -12, 11, 6, 5, 1, 19, 9, -26, 14, 0, -5, -15, 16, 3, 10, 9, -7, -15, 11, -12, 1, 12, 0, 18, 3, -16, -8, -5, -8, 2, 15, -3, 4, -6, 16, 0, 4, 14, -1, -2, 12, -6, -11, 10, -3, -3, -12, -7, 3, 5, 5, -1, -1, 10, -2, -2, 9, 3, -24, 13, 5, -10, 21, 9, -21, 4, 4, -1, -38, 16, 1, 12, 16, -3, -23, -13, 18, 11, -13, 0, 15, 12, 3, -10, -23, 6, 14, -10, -17, -5, 1, -2, 16, 0, -11, -7, 14, -3, -6, -8, -4, 8, -12, 5, -1, -5, 11, 7, -9, -7, -3, 12, 3, -11, 2, 3, -10, -2, -5, -11, 8, 11, 4, -13, -8, 14, -1, 10, 5, -10, 10, 2, -12, 1, -5, -7, 8, 12, -9, 11, 11, 0, -19, 6, -15, -5, 5, -10, 2, -5, 14, -7, -17, 11, -22, 0, 6, -12, 7, 11, 35, -5, -2, 20, 1, -7, -2, -10, -6, 2, 26, -16, -12, 23, 0, 11, -6, -3, -3, 11, 21, 1, -6, 7, 10, 9, -2, 8, -7, -5, -2, -11, -7, 19, 14, 5, -8, 1, -9, 13, -22, -2, -8, 21, 16, 2, -10, 7, -3, -3, -12, -7, -4, 11, 1, 2, -3, 0, -20, -2, 5, -20, -3, 17, 4, 8, -9, -14, -1, -8, 10, -16, 10, 18, 7, 9, -13, -7, 7, -17, 11, 7, -4, 12, 0, 4, -14, -18, 47, -22, -17, -12, -11, 23, 0, -13, 9, -7, 56, -8, -54, 1, -1, 13, -12, -12, 6, -21, 26, 3, -40, 14, 22, 24, -15, -13, 1, 3, -11, -5, -32, 16, 10, 16, -14, -8, 1, -3, -22, 0, -11, 12, 0, 2, -8, 8, 13, 20, -29, -1, 18, 38, -4, -23, 16, 12, -10, 16, -13, -10, 29, 28, -12, -29, 12, 4, 13, 16, -5, -3, 19, 20, -9, -37, 11, 0, -4, 15, -4, 18, 26, 7, -24, -27, 6, 7, 7, 8, 0, 20, 22, 2, -27, -25, -19, -1, 4, -12, 2, 8, 18, -7, -31, -2, -7, -10, 3, 8, 15, -3, -1, -10, 0, -1, 5, -8, -9, 20, 1, 18, -2, -23, -9, 6, -19, -8, 3, 21, 29, 13, -5, -21, -29, -9, -24, -11, 15, 10, 17, 11, -30, -9, 3, 4, -23, 5, -1, -11, 2, -14, -33, 9, 28, 9, -2, -15, 14, -22, -14, -2, -27, 22, 32, -1, -22, 8, 11, -16, -10, -3, 4, 10, 26, 4, -7, 12, -11, -8, 0, -7, 22, 8, 7, -18, -12, 10, -7, -10, -2, -15, 20, 15, 8, -23, 16, -3, -4, -11, 8, -3, 12, 0, -1, -18, -3, -6, -4, -18, 9, -18, 27, 6, 16, 4, 15, 4, -13, 13, 2, -4, 7, -17, -5, 21, 20, -6, -13, 23, 5, 4, -7, -19, -8, 18, 27, 1, -7, 28, -8, 20, -5, -6, -10, -10, 21, 10, -1, 4, -29, 26, 12, -4, -23, -26, 3, -8, 3, 13, -9, 18, 14, 10, -7, -15, -1, -7, -1, -2, -14, 14, 10, 10, -4, 1, 5, -18, -2, -18, 9, -5, -10, 11, -21, 1, -1, -14, 13, 5, 3, -18, 1, 13, -23, 11, 11, -6, 1, 13, 21, -31, -25, 2, -19, 20, 15, 9, 8, 16, 4, -16, -10, -4, 14, -4, 7, -2, 3, -15, -2, -14, -4, 19, 28, -5, 10, 18, -3, -7, -14, -10, 11, 20, 17, 5, -7, 21, -5, -14, -11, 5, -3, 17, 26, 2, 3, 0, 5, -21, 3, 3, 2, 14, 12, -6, 8, 16, -2, 11, 2, 9, -3, -14, -13, 3, 4, -7, 7, 0, 5, -13, -6, -4, -1, -6, -10, 0, 3, 7, 9, 5, -11, -7, -2, 2, -11, -6, -6, -12, -1, -5, 1, -6, -2, -23, 6, -10, 10, -7, 12, 4, -19, -1, -8, -4, -5, 0, 4, -3, 9, -14, -34, 5, -13, -9, -1, 3, -4, 3, 0, -3, -14, 3, 8, 3, -12, 14, 6, 8, -15, 2, -7, 22, -4, -2, -6, 17, 5, 7, -24, -6, -9, 26, -2, -4, -10, 18, 6, 1, -27, -2, -4, 9, 46, 1, 0, 12, 0, -12, -18, -4, 14, 20, 43, 6, -15, -7, -11, -1, 18, 11, 30, 16, 0, -17, -9, 3, -8, -5, 41, -4, 20, 1, -22, -6, 3, 4, -1, 0, 58, 3, -6, -36, -15, 5, 27, -9, 13, 1, 40, -3, -38, -41, -5, 8, 4, -10, 16, 20, 21, 7, -39, -33, 29, 22, -9, -12, 10, 9, -12, -10, -17, -14, 38, 31, -24, -16, 13, -5, -30, -8, 21, -4, 31, 10, -4, -9, -15, 6, -18, -15, 30, 14, 7, 7, 12, -1, -16, -4, 3, -20, 6, 2, -8, -17, 6, 2, 5, 7, -10, -10, 5, -11, 3, -4, 15, 10, -3, -9, -5, 15, -8, -9, 2, -5, 13, 4, -14, 12, -1, 7, -1, 2, -8, 0, -1, -1, -5, 2, -10, 11, -3, -6, -5, 3, -8, -5, -4, -7, -4, -4, -4, -4, 0, -9, -10, 8, 5, 10, 7, -2, -20, 15, 10, -4, -13, 2, -9, -9, 26, -7, -16, -2, 1, -4, -13, 10, 1, -3, -7, 0, 0, -7, -3, -16, -6, 3, 0, -5, -4, -6, 4, 0, -2, -9, 5, -9, 3, 12, -4, -15, 15, -13, 2, 3, 9, 1, -13, -2, -9, 3, -11, -2, -6, -1, 14, -1, -5, -4, -5, 3, 6, 18, 1, 9, 2, 13, -6, -8, -12, 2, 0, 21, 8, -7, 5, 4, -7, -10, -1, 13, 8, 16, 6, -25, -8, -7, 4, -5, 15, 19, 0, 13, -11, -8, -7, -11, -2, 15, 35, 18, 12, -20, -62, 8, 3, 5, 14, 5, 41, 20, 5, -53, -52, 14, 26, 4, 7, 24, 19, -7, 2, -35, -51, 34, 25, 6, 1, 21, 2, -19, 2, -22, 18, 18, 21, -2, 3, -8, -22, -15, -8, 25, 29, 11, 3, -3, 1, -6, -11, 1, -5, 23, 33, -11, -16, -4, -1, -14, -9, 9, -5, 20, 13, -20, -11, 3, -13, -15, 1, 6, 7, 10, -2, -17, -16, 13, -10, -9, -23, 5, 6, -3, 9, -12, -21, -9, 14, 17, -21, -2, 4, 3, -4, 15, -19, -10, 14, 4, 5, -8, 1, -17, -10, 28, -11, -10, 2, 10, -7, -16, -2, -10, 3, 24, -12, -16, 0, 10, -1, -10, -9, 4, -10, 1, 1, 1, 2, -5, 8, -2, -4, -2, 11, 8, -3, 14, -6, -6, -3, -5, -2, 10, 8, 8, 4, 9, -8, 12, -2, 1, -8, -11, -7, 6, -3, -4, 7, -4, -8, 7, -9, -9, -3, 0, -6, -4, 14, -7, -23, -5, -1, -7, 15, -2, -13, 4, 3, -18, -4, 9, -5, 13, 18, 0, -20, 9, -10, -1, 0, 11, -18, -2, -2, 4, 2, 15, -14, -1, -7, 22, -3, -6, -18, -7, -12, 17, 1, -17, 11, 23, -5, 3, -3, -5, 2, 10, -21, -11, 7, 20, 4, 2, -13, -1, 20, 10, -5, -9, -7, -6, 6, 20, -11, -17, -10, 17, -16, 19, -3, -23, 21, 20, 3, -8, -9, 21, -3, 14, -5, -23, 21, 15, 13, -9, -8, 4, 17, 1, 2, -35, 24, 27, 19, 1, -5, -10, -5, -8, -8, -17, 12, 41, 8, -20, -5, 3, 10, 5, -4, -16, 30, 33, 26, -12, -21, 15, 14, -11, 3, 6, 7, 10, 17, 0, -18, 21, 2, 1, 0, 16, -10, 3, 10, 12, -10, -3, -6, -6, 10, 32, -33, -30, 16, 26, -1, -2, 11, 0, -9, 32, -35, -28, 22, 36, 6, -8, 13, 4, -6, 24, 2, -14, 7, 16, -10, -10, 11, 21, -7, 23, -10, 5, 11, 5, -6, -21, -1, 5, 1, -14, 10, 9, -2, -8, -2, -1, 0, 6, 6, 7, 3, -1, 8, -17, 14, 8, -10, -4, 10, 3, 2, 12, -9, -3, 0, 0, -3, -9, 12, 6, 8, 16, 1, 1, 12, -3, 0, -13, -13, -4, 9, 15, -1, 1, 2, 4, 3, -15, -2, -15, 21, 7, -10, -7, 16, 7, -4, -11, -10, -13, 11, 20, 3, -9, 7, 1, -6, -1, -21, -12, 19, 18, 3, -9, 5, 9, -2, 1, -20, -35, 34, 23, -2, 3, -4, -5, 14, 7, -27, -31, 23, 14, -5, -3, -3, -32, 21, 23, -14, -21, 2, -12, -8, -5, -13, -24, 9, 13, 2, 7, -10, -37, -5, 12, -3, -13, -1, -7, 16, 21, -16, -25, -12, 4, 3, -6, -19, -12, -4, 30, 15, -8, -5, 1, 4, -10, -13, -14, 2, 5, 10, 13, -2, -11, 0, -15, 13, 1, -5, 5, -7, 25, 1, 12, 1, -8, -13, -4, -1, -18, -10, 3, 8, 10, 7, 4, 1, 7, 6, -5, -21, 13, 11, 28, 7, 17, 4, -15, 17, -7, -19, 8, 4, 24, 16, 0, -7, 16, 3, 19, -11, -18, 12, 18, 4, 0, 4, -1, -16, 23, -12, 3, 22, 12, -18, -14, 12, 13, -17, 17, 9, -9, -2, -4, -23, 2, 8, 8, -19, 20, 10, -10, -2, -5, -12, 6, -14, -13, 0, 6, 10, -11, 4, -16, -6, 14, -15, -13, 18, 2, -5, -3, 5, -13, -4, 11, -1, 0, -1, 0, -4, -7, 4, 0, -1, 19, -2, -3, 26, 0, -9, 6, -4, -12, 8, 2, 14, 3, 23, -16, -2, 6, -10, -1, 1, 0, 8, 13, 12, -7, 1, 4, -12, -8, 9, 0, -8, 10, 15, 5, 2, -2, 0, -3, 8, 0, -4, -1, -1, 3, -21, 6, -21, -1, -12, -2, -2, 3, 4, -13, -4, 1, -15, -13, -17, 5, -7, -7, -3, 10, -11, -10, -9, -8, -9, -16, 3, 5, 0, 23, -3, 11, -18, 9, -1, -8, -13, -12, -10, 1, -3, 9, -11, -9, 9, -4, -13, -5, -14, 17, 13, -4, 0, -20, -6, -6, 11, 1, -5, 16, 18, 0, -6, -18, 13, -31, 12, -7, 3, -5, 16, -3, -22, 9, 30, -17, 23, 0, 39, -27, -8, -20, -29, 4, 31, -17, -2, 10, 30, -17, -16, -29, -21, -13, 28, 13, -7, 12, 31, -25, -10, -12, -15, -5, 23, -3, -3, -20, 22, -28, -24, -8, -3, -12, 19, 7, -9, -11, 4, -8, -10, 9, 16, 8, 8, 9, 17, 11, -25, -12, -4, 13, 14, 5, 0, 16, 4, 24, -32, 18, 19, 0, 12, -7, -23, 11, 10, 21, -18, 6, 28, 3, 10, -9, -9, 7, -10, 9, -20, 14, 23, 5, 17, -15, 1, 9, -6, -1, 2, -7, 2, 0, 7, -2, -2, -6, -10, -12, 1, 4, -11, -2, -1, 10, 1, -2, -5, -18, 4, -4, 5, 1, -10, 2, 5, -10, 2, 6, 14, -13, 5, -5, -14, 8, 7, -13, 19, 4, 10, -13, -2, -1, -13, 5, -15, -5, 1, 10, -4, 5, 5, 0, -17, 8, -17, -13, 4, 7, -5, 16, -8, 4, 4, 5, 0, -5, -10, -7, -14, 24, -4, -1, 1, 0, -3, -9, 9, 0, -7, 5, -2, -1, -4, 2, 6, 1, -11, 0, -3, -15, -4, 6, 3, 13, 4, -7, -3, -16, -8, -10, 14, 11, 3, 8, 0, -2, 0, 3, -4, 2, 13, -1, 15, 11, -8, -4, -13, 1, -2, -5, 13, -3, 2, 1, -10, -5, -1, 1, 10, -6, 7, -15, -10, -1, -7, 1, -4, 2, 25, 4, -8, -5, -8, -6, 3, -1, 0, -8, 4, 20, -2, -10, 3, 4, 4, 11, 4, -5, 8, 25, -24, -4, -7, 17, -6, 4, 1, 2, -19, 26, -27, -1, 1, 6, -14, 11, -11, -2, -11, 28, -38, 6, -13, -4, 10, -6, 3, 7, -23, 35, -21, 5, -20, -19, 20, -7, -11, 1, -15, 28, -7, -5, -17, -17, 9, -8, -2, 1, 9, 22, -11, -9, -28, -30, 1, -5, 5, -1, 14, 23, -3, 3, -23, -4, -3, -3, 16, 1, 20, 14, -9, 2, -7, 14, 0, -8, 16, 16, -6, -9, -8, -6, -12, 24, 22, 8, 9, 5, -8, -9, -21, -31, 9, 22, 14, 3, 13, 6, 2, -20, -18, -18, 11, 13, 30, -5, 3, 24, 17, -17, -1, -11, 19, 20, 21, 15, 6, 4, 7, -31, 0, -3, 24, 0, 17, 3, -11, -8, -11, -10, 3, 28, 21, 9, 3, 12, 5, -12, -23, -22, 19, 15, 29, -6, 5, 9, -1, -11, -5, -19, 23, 20, 11, -10, 3, 10, -11, -8, -16, -2, 4, 3, 15, -7, 7, 14, } +#define IP1_BIAS {-54, 34, -49, 9, -32, -32, -4, 30, -32, 10, 17, -29, 54, -22, 14, -8, -13, 6, -60, -42, -56, 33, 18, 82, -56, 109, -18, 22, 38, 50, 29, -4, 18, -12, 60, -25, -27, 28, 24, 38, -15, -18, 1, -17, -41, 11, 10, 11, -8, -35, 15, -20, -8, -26, 1, -36, -59, -59, -11, 22, -5, 31, -84, -20, 15, 32, 95, -12, 42, -24, 28, 21, -10, -28, -26, -46, 50, -34, 29, 41, 2, -35, 7, -69, -53, -55, -25, 20, 79, -65, -48, -17, -41, 25, 8, -5, 58, -14, 25, -80, 11, -62, 56, 4, -59, -32, 44, 18, -10, 19, 1, -45, -29, -30, -11, 7, -2, 7, 18, -22, -16, 24, -44, 16, -12, -78, 21, -58, -2, -12, -27, 4, -2, 12, -7, 1, -6, 61, 2, -31, -13, -39, -14, -39, } +#define IP2_WT {-12, -25, -30, 8, 26, 21, -26, 3, -28, -49, 0, -20, 20, -33, -13, -40, 0, 30, -44, 4, 18, -37, -27, -3, -33, 3, 20, -13, -7, 4, -16, 35, -42, -11, -2, -7, 12, 43, 6, 1, -10, -52, -4, 38, -23, -6, 28, -38, -12, 18, -19, 11, 9, 25, -47, 21, -28, -57, -4, -5, 19, -1, -5, -27, 52, -4, -26, 26, -17, -16, -2, 2, 34, -33, 45, -16, 4, 21, -20, -5, -21, -10, 17, 35, 28, 13, 21, -20, -13, -3, -2, -10, 44, -18, 2, -42, 28, 4, 28, 54, -19, 13, -8, -5, -33, -57, -2, 58, 53, -14, 11, -17, -1, 31, -33, -29, 16, -1, -4, 2, 43, -22, 24, -34, 23, 3, 4, -49, 44, 25, 14, 0, 31, 26, 0, -43, 5, 9, 38, -37, -27, 52, 0, 51, 24, -8, -24, 18, 16, 44, 36, 15, -3, -28, 29, -9, -11, -11, -7, 6, -17, -1, -56, 13, -40, -34, -20, 33, -27, -5, 38, 14, 29, -9, -61, -24, -38, -49, -38, -38, -10, -14, -25, -27, -11, 36, 6, 22, -25, 7, 16, -41, 8, -15, 21, 27, 33, 28, -29, 2, -22, 23, -19, -10, -2, -6, 1, -5, -30, -14, -4, 15, -34, -44, -22, -7, -14, -18, 32, 22, 7, 15, 40, -2, 30, 37, -63, 20, 26, 24, -28, -13, -24, 29, -5, -22, -11, 24, -39, 19, -2, 13, 31, 14, 15, 23, 30, -15, 7, 1, -14, 49, -21, 30, -8, 0, -39, -68, -13, 1, -25, 33, -12, -8, -45, 24, -9, -21, -11, 18, -27, -18, 32, -17, 19, 30, 28, -37, 0, -18, 31, -61, 19, -7, 8, -8, 17, -9, -24, -10, -9, -52, -16, -10, 21, 1, -58, 11, -26, -20, 49, -4, -19, -51, -13, -16, -11, 24, -8, 25, 9, 2, -11, 7, 45, 14, 22, -43, 6, -44, -7, -26, 25, 4, -37, -48, 24, -16, -21, -12, -21, 22, -8, 36, -27, -71, 20, -1, 7, -16, 34, 9, 26, 4, -2, 35, 11, 20, -20, 25, 18, -15, -34, 5, 25, 24, -2, 4, 24, -12, -1, 8, -26, 4, 4, 4, 5, 4, 41, -8, -11, 15, -45, -21, -50, 42, 4, -46, 37, 31, -55, 14, 13, 1, 29, -6, -2, -19, -1, -17, -5, -7, 15, -39, -19, -4, -20, -8, -15, 18, 0, 45, -16, 15, -1, 3, -17, 3, 17, -33, -8, 28, 1, -23, -36, -11, -50, -20, -3, 1, -1, -9, 26, -2, -16, 33, -28, 20, -37, 29, 24, 2, -4, -11, 21, 16, -24, -21, -22, -38, 47, -46, -11, 15, 28, -13, -39, 44, -25, 12, -6, 22, -56, 21, -12, -28, -28, -38, -3, -31, 11, -21, -26, -16, -45, -4, 3, 2, -25, 29, 6, 6, 24, 25, -40, -59, 27, -21, -8, -22, -16, -49, -6, 16, -16, 46, -19, 8, -7, -18, 6, -8, 22, -11, -36, -41, -4, -21, 0, 17, 1, 16, -41, -34, -40, 2, 3, 19, 20, 18, 19, -12, -15, 41, 50, -7, 40, 23, -7, -22, -29, 16, 16, -9, -6, -2, -8, 29, 32, 14, 24, -18, -16, 33, 0, -32, 22, -16, 17, -16, 10, 2, 24, -14, -8, -31, 38, -22, -3, -30, 13, -45, -39, 30, 13, -26, -26, -14, 3, -24, 27, 53, -2, 17, -8, -39, -5, 7, -7, -37, 21, -20, -33, 39, -19, 7, -9, 3, -2, -52, -2, 13, 39, 19, -17, -34, 12, -3, 37, 3, -9, 36, -22, 35, 3, -32, 34, 45, -41, -2, 12, 22, 24, 37, -6, 6, -25, -11, -35, 10, 15, 35, -28, -16, -19, -19, -2, -43, -44, 15, 46, -19, -21, 27, -30, 14, -1, 16, 50, -22, 1, -17, 33, 25, -12, 20, 27, 0, -28, -3, -19, -23, -24, 33, -48, -74, 16, 13, 16, -18, -25, -37, -33, 1, 39, 7, 1, 16, -12, -35, -15, -24, -14, 1, 9, -32, 31, 25, 9, -33, 43, -41, -17, 6, -13, 21, 34, 24, -10, 30, -14, -13, 0, 28, -28, -8, -32, 11, 8, 10, 43, -18, -37, 22, -17, 23, -2, 0, -15, -31, 21, -30, 15, -45, 41, 14, 13, 38, 6, -7, -6, -21, 22, 41, -14, -18, 28, 13, -1, 11, 25, 38, 7, 11, 27, 33, -13, -20, -48, 23, 24, 51, 13, -25, 4, 24, 10, 28, 0, -1, -18, 9, 15, -10, -13, -28, -3, 8, 3, -39, -54, 31, 2, -17, 19, -9, 27, -28, 0, 0, 33, 6, 33, 28, -5, 3, 9, 10, -4, -23, 31, -17, 28, -20, 46, 32, 46, 1, -20, 17, -12, -20, 36, 33, -10, -41, -21, 18, 25, -33, 26, -1, -21, -1, -29, -58, -40, -21, 7, -40, 1, 25, -5, -6, 3, -1, 3, -57, 49, -7, 11, -39, 28, -50, 51, 9, 4, 40, -8, 20, 3, -36, 32, 10, 28, -27, -57, -19, 1, 24, -58, 1, -55, -28, 37, -5, -13, -12, 35, -15, -34, -16, -49, 28, -31, 22, -22, -20, 5, -20, 17, -25, 75, 2, 1, 12, -63, 4, 1, -35, 16, -1, -10, 20, 14, -31, 22, 13, -17, -27, -16, 23, -24, -17, 30, -3, 44, 28, 22, 31, 10, -48, 16, -19, 3, -27, 24, 2, -40, 28, -30, 1, -38, -18, 14, -10, -76, -18, 13, 6, 2, 38, -27, -18, -16, -22, 16, 25, -41, -4, 6, 16, -27, 16, -54, -13, -7, -27, -32, 52, -1, -23, -16, -35, 51, 30, 3, -17, -52, -18, -25, -25, 9, -16, 35, 20, -35, 19, 31, 7, 31, -5, -34, -3, 48, 8, -14, -16, 4, 12, 2, -1, 36, -20, 44, 36, 10, 5, 5, 29, 16, -15, 1, -16, -12, -3, -21, 14, -8, 5, -62, -30, -39, 23, 29, -20, 58, 6, -16, 30, 4, 15, 22, 5, -48, 22, -30, 11, -23, -8, -4, -40, 9, 19, -41, 16, -35, -45, -28, -4, -41, 29, -12, 16, 29, -5, -11, 18, -18, -24, -8, 19, 9, 30, -35, 43, -4, 5, -36, 3, -1, -2, 26, -8, 13, -3, -12, 14, 14, 27, -23, -27, 26, 32, -18, 42, 11, 10, 37, 22, -15, 2, -27, 25, 10, 1, 35, -13, -29, 13, 9, -34, -10, 43, 27, 0, -29, -18, -14, 14, 9, -3, 23, 28, 29, -14, 14, -34, 10, 31, -13, -25, 55, -31, -6, -27, -27, -34, -48, -4, 35, -5, -2, -19, 37, -39, -21, 27, 1, 18, 35, -23, -49, 33, 17, 41, 23, 1, 30, -19, -31, 29, 11, 21, 36, -2, -35, 20, 33, 7, 12, -6, 7, -2, -22, -24, 19, 34, 22, -14, -31, -14, -8, 8, -37, 17, -35, -6, -29, 3, -3, -21, -6, 3, -7, 15, -29, -49, 41, 29, 19, 2, -35, 34, 39, -9, 17, -23, 25, -34, 9, 20, -19, -8, -14, -11, 14, -15, -28, 9, -37, 44, -6, -19, -4, -27, 30, -33, -19, 41, 4, 2, -14, 34, 11, -11, -2, 8, -16, -26, 7, -4, -24, -6, -1, 28, 16, -30, 22, 6, -36, -26, -2, -9, 46, 5, -13, 2, -14, -11, -8, 24, 26, -6, -36, -33, 13, 13, -20, 5, -8, 37, -41, 11, 9, -25, -4, 5, 29, 0, -30, 3, -4, 19, 9, -19, 31, 6, -25, 22, 7, -20, 29, -4, -21, 23, 9, 19, -1, 26, 42, -31, -6, 31, -7, -30, -28, 5, 26, -6, -12, -42, 9, 25, 11, 1, -34, -27, 12, 15, 21, -17, 26, 45, 4, 31, 0, -29, -16, -17, -36, -14, -26, -11, 42, -50, 43, -4, 6, -36, -43, -33, 37, 35, 38, 17, 20, 28, -19, 20, 31, -5, 13, 1, 4, 18, 27, -36, 27, 1, 5, 30, 31, -12, 48, 41, -10, -22, 21, 36, 12, 8, -14, -64, -3, 2, -20, 46, -20, 0, 20, 29, -20, -49, -27, 44, -11, -7, -5, 24, 1, -25, 16, -22, -35, -6, 5, -2, -9, -14, 22, -2, -4, 22, 26, -35, -12, -41, 29, 33, 28, 1, 4, -30, 11, 18, 31, -34, 44, -23, 25, 38, 20, -29, 3, 24, 3, 8, 41, -18, 13, 16, -6, -37, 28, 26, 4, -6, -11, 14, -30, -22, 31, 31, -15, 4, 32, -33, -42, -49, -51, 21, 13, 33, 9, 43, -19, -40, 20, -19, -59, 18, 7, -9, -13, -8, -2, -7, -16, -28, -43, 6, -31, -20, 13, -21, 38, 29, 4, -34, -10, 64, -5, 35, 4, -15, -10, 20, -32, 42, -19, -54, 28, -7, -35, -13, 33, 20, 4, 28, -14, 1, -57, -8, -68, -20, -7, -3, -17, -4, -7, -18, -1, -33, -3, 12, -19, 12, -33, -51, -31, -17, 44, -14, 20, 15, 10, 6, 6, 16, -17, -40, 10, 35, 18, 11, 39, -18, -14, 15, 11, -16, 2, 0, 2, 18, 6, -5, 10, -11, -31, -53, 3, -14, -9, 13, 47, -36, -32, 16, -25, -40, -63, 19, 36, -1, -11, -2, -15, 19, -22, 21, 47, 12, -37, 14, -13, 2, 3, 8, -33, -5, 0, 39, 5, -7, -6, -25, -32, 31, -12, 9, -8, 23, 2, -28, -40, 45, -20, -34, -13, 19, -4, -24, 22, -22, -27, -39, 50, -10, 28, -49, -37, 16, -28, 40, -8, 17, 16, -32, -7, 18, -4, 23, -40, 3, -9, -19, -7, 8, 26, 27, -17, 11, 69, 36, -34, 25, -32, 43, -8, -42, 34, -25, -1, 20, -24, 10, -34, -7, 44, 12, 2, -6, 28, -1, -1, 26, -9, 64, -45, -12, -13, -44, -55, -6, -1, 38, -4, 4, 37, -39, 9, -12, 0, -73, 35, 51, -27, 0, 0, -50, -15, 0, 0, 0, -34, -12, 29, -4, -18, 31, 1, -13, -34, 20, -27, -39, 0, -28, 77, -6, -10, 29, -5, 13, -28, -14, -65, 24, 5, 1, -25, -59, 30, -65, -14, 33, -68, 8, -17, -19, 2, 6, -16, -5, -36, -19, 9, 10, -32, -19, -11, -40, -27, 18, -26, 4, 10, -21, 18, 34, -4, -49, -14, 29, 23, 56, 17, -54, 21, -33, -29, -9, 2, -6, -65, -38, -21, 26, -8, 4, -45, -21, -19, 24, -29, 3, 20, 7, 25, 6, -6, 15, -15, -16, -3, 24, -46, 1, 6, -22, 47, 53, 16, 39, 10, -4, -6, 10, 12, 30, -38, -39, -22, 15, 0, -21, 28, 24, -8, 40, 46, 27, -14, -43, -51, -52, 10, -9, -19, -8, 15, -18, -25, -30, 33, 0, 14, 13, -35, -69, -27, -15, 31, -10, -28, 28, -19, 21, -1, 59, 43, 16, 6, -37, -10, 32, -30, 22, 2, -31, -26, 6, 28, 14, -31, -43, 6, -29, 30, -24, 12, -26, 6, -37, -27, -8, -32, 22, -27, -40, 44, -35, 13, 18, 46, -27, 32, 42, -25, 39, 6, -17, -31, 10, -29, 14, -3, -33, 14, -1, -9, 43, -30, 19, 13, 8, 3, -22, -22, 7, 1, -10, 2, 11, -22, 30, -7, -10, 37, -51, 42, 6, -30, -21, 20, 17, -24, 16, -5, 19, -6, -17, -11, 18, 12, 27, 34, 15, 18, -2, 20, -22, -26, -37, -25, -35, -20, 4, -10, 32, 13, 4, 10, -14, 16, -9, -16, -26, 23, -10, 19, -25, 28, 8, 34, 7, 39, 13, 4, 4, 27, 6, -7, 14, 29, 15, -20, 10, -14, -18, -6, 1, 25, -32, 20, 22, 26, 14, 0, 15, -12, 12, -14, -18, 19, -10, -21, -24, 4, 43, -11, 28, 35, -2, 18, -7, 35, -16, -33, -17, 13, -17, -13, 1, -24, -12, -18, 32, 27, -25, -32, 2, -8, -19, -1, 28, -19, -40, 22, -14, -12, -16, -6, 21, 14, 12, -11, -26, -30, -19, -25, 2, 35, -16, -9, 34, 8, -2, -34, 12, -3, -10, -14, 48, 54, -21, 41, -28, 10, -19, -19, -21, 13, -9, 33, 3, 18, 30, 26, -1, 27, 1, 17, 34, -64, -41, -18, -1, 10, 21, 6, 9, 11, -20, 33, 12, 2, 33, -32, -19, -55, 28, -30, -9, 35, 48, -32, -25, 11, 12, -33, 27, 0, 18, -15, 4, 3, 12, -47, -10, 12, 25, 36, -16, -6, 14, 37, -30, 7, 28, 20, -4, -20, -9, 19, -44, 14, -21, 25, 15, -6, 43, 10, -11, -32, 10, -1, 1, 3, -46, -17, 23, -69, 27, -9, 27, 13, -26, 26, -7, -19, -8, 28, 9, -8, 7, 40, 2, 2, -49, 20, -35, -20, -7, -23, 4, 17, -44, 13, 17, -9, -35, 3, 5, 38, 33, -19, -10, -30, -17, 4, 22, -25, 29, -21, -9, 6, -15, -14, -32, -40, 16, 6, -32, -12, -38, 14, 11, 6, -14, -15, -44, 44, -40, -13, 24, 20, -39, 16, -28, 49, -18, -41, -13, 9, 14, 51, -45, -19, -13, 29, -15, 7, -11, 3, 50, 45, -22, -43, 0, -17, 0, -18, -43, -30, -49, 38, 11, 29, 4, -2, -26, -20, 27, -33, 19, 4, -19, -1, 26, 13, -14, 8, 19, -27, -12, -26, 15, 34, 36, 35, 7, 25, 43, -10, -33, 17, 52, -25, 31, -4, 7, 37, -53, -4, -18, -23, -33, -9, -36, 33, 14, 9, 13, -7, 12, -31, 26, -15, -46, 23, 7, -11, -23, -11, -9, -12, -36, 3, 13, 0, 16, -10, -20, 45, 21, -12, -42, 0, -4, 12, 27, 21, 2, -28, -35, -13, -11, -12, -23, 8, 27, 15, 32, 24, -13, -7, 8, 14, 28, -1, -34, -6, -24, 21, -14, 12, 16, 32, -13, 7, 1, -22, -41, 37, 11, 31, 24, 32, -19, 17, -8, -40, 16, -7, -2, -3, -1, 17, 5, -36, -44, 12, 42, -4, -23, -18, 19, -9, -7, 35, -36, -17, -21, -36, 7, -13, -3, -18, 26, -23, -24, -29, 31, -36, -22, 38, 1, 2, 9, -31, 17, 18, -47, 12, -19, -36, -21, 28, 26, -5, 28, 24, -19, 11, 30, 18, 25, -15, -25, 14, 5, 1, -10, 36, -25, 22, 6, 38, -12, 4, 5, -24, 10, -25, 28, -15, -6, 28, -15, -13, -31, 12, -36, -34, -2, -30, 1, -23, -15, 26, 4, -7, 24, 35, 9, 8, 20, -5, -1, 20, -26, 3, -14, 15, 31, 24, -39, -25, 2, -20, -3, -4, -36, 27, 3, 23, 13, -3, 26, 40, 10, -35, -27, -8, -12, 2, 33, 8, 31, -43, -27, 10, 2, -42, 3, -1, -15, 27, 2, 24, -35, 33, -7, -50, 28, 7, -25, 13, -25, 25, -24, 33, -15, 16, 29, 37, 2, 26, 5, -9, 26, 8, -65, -4, -18, -26, -35, 7, 24, 11, 24, 22, -26, -23, 11, -64, -27, 29, -50, -24, -40, -18, 12, 20, 36, 6, 18, 4, -12, 27, 20, -27, 55, 22, -2, 3, 25, -2, -22, 2, -25, 22, -6, -13, 14, 12, 21, -26, 59, 20, 16, -16, 34, 17, -31, -40, 21, -29, 28, -21, -19, 7, 28, -9, 0, -38, 8, -5, 20, -46, -12, -10, -6, -32, -35, -4, -8, -50, -29, -10, 54, -26, 29, 12, -5, -30, 1, 19, -6, -45, 42, 28, -3, -44, 20, -28, 0, 39, -3, 15, 17, -23, 9, -25, 6, -35, -8, 23, -30, 3, 12, 22, -28, 20, -12, -63, 50, -12, 16, 21, -10, -32, -45, -6, 31, 15, 10, 27, 36, -1, -19, -8, -14, 28, -25, -5, 8, 39, 12, 13, -56, -11, 0, 46, 24, -21, -40, -41, 32, 31, 33, -19, 32, -48, 51, -12, -4, -18, -23, -7, 21, 22, 15, -50, 11, 8, 8, -30, -9, 10, 40, -12, 36, 35, -30, -14, -13, 26, -29, 8, 27, 29, 27, -31, 29, 0, -1, 22, 70, -27, -25, 50, 44, -11, -6, 5, -39, -10, 2, -44, 10, 9, -6, 17, -25, -17, 6, -28, -9, 2, 21, -42, -23, -9, 37, 18, -22, 12, -17, 18, -1, -3, 29, -34, -7, 3, -2, 0, 9, 37, -6, -22, -19, -27, -1, 17, 27, 17, -16, -26, -86, -29, 7, 12, -38, 11, 8, 1, -17, 40, -43, -10, 11, 4, -5, -10, -7, 22, 4, -52, 10, 2, 0, 14, -29, 20, 7, -39, -3, 43, -41, 25, -30, 21, -5, 23, 13, 59, 25, -13, -10, -46, -27, -24, -19, 27, -29, 16, -22, -24, 16, 27, 32, -43, 25, -42, -11, 35, 17, -7, -23, -32, 28, 1, 25, 41, -16, -26, -20, -12, -22, 8, -16, 12, -35, 1, 10, -25, -38, -33, -14, -34, -42, -53, 40, -20, 2, 9, -10, -2, 35, -5, -16, 5, -29, -5, -3, -5, -24, -19, 38, -24, 30, -17, -26, 1, 36, -29, 9, -29, -17, 23, -28, -3, -7, -4, -40, -35, -26, 1, 25, 2, -3, 40, -2, -22, -13, -17, -1, 16, 18, 33, -23, 29, -8, -16, -11, 48, -33, -12, -14, -4, -50, 1, -22, -25, 2, -21, -16, 5, -22, -22, 18, -43, -36, -18, 32, -19, -25, -3, 12, 11, 32, 14, -17, 37, 5, 58, -63, -24, 27, 15, 20, 30, -11, 31, 49, 22, 9, 16, -37, 26, -17, -26, -19, 47, 23, 21, -5, -52, 39, 14, 41, -14, -46, -30, -1, -44, 5, -50, 40, -20, 21, -38, 30, -34, 0, -9, 24, -4, 5, -40, 37, -45, -24, 20, 22, -8, -55, -28, -18, 32, 6, 36, -9, -4, 14, 10, -54, -1, 8, 34, -7, 17, 3, -38, 11, 0, -5, 22, 12, 7, 23, -12, -47, -14, -19, 1, -51, -18, -27, 5, -14, -10, 31, 21, 18, -7, -5, -18, 21, 30, 36, 14, 2, -34, -2, -27, -16, -35, 9, 36, -7, -26, 35, 16, -26, -26, 9, -39, 5, -29, 26, -12, 46, 20, 42, -7, -29, -31, -64, 50, 12, -24, -29, 73, -32, 5, 23, -50, -24, -17, 2, -21, 28, -7, -35, -2, 5, -26, 55, 50, -2, -11, -2, -7, -3, 29, 44, -6, 4, -23, 15, -19, 29, 2, 19, -17, 23, -9, 13, 5, -10, 10, 0, 19, 18, 3, -17, -4, 9, -17, 3, -18, -7, 3, -22, -26, 38, 49, -13, 4, -31, -22, -68, 64, -4, -3, -19, -7, -17, -24, 0, 23, 6, -13, -40, 5, 8, 26, 5, -2, -32, 41, 9, 2, -8, 26, -16, -16, -43, 10, 1, 21, -3, 21, 31, -45, 7, 6, -34, 2, 26, 54, -4, -10, -18, -14, 13, -34, -40, 30, -5, 30, -13, -36, -9, 18, 59, -21, -5, 31, -15, 35, -31, 39, -16, -7, -2, 0, -18, -20, 21, 24, -44, 7, -13, -30, -68, 34, -27, -55, -11, 70, -34, -22, 26, -8, 8, -4, -18, -22, 29, -57, 26, 23, 20, 2, 13, 26, 1, -13, -28, -7, 7, 4, 33, 22, 38, -47, -20, -5, -7, -16, -35, 3, 0, -27, -12, 22, -15, -15, -28, 12, 71, 31, -37, -32, -21, 11, -23, -42, 14, 6, -42, 38, -1, -5, -5, -11, -14, 46, 29, -6, 21, 12, 9, -29, -8, -38, -1, -3, 17, 23, 7, 21, -3, 24, 11, -8, -6, 7, 0, 5, -32, -58, -12, 33, 15, -34, 18, -4, -16, 31, 9, 14, 3, 24, 47, -38, 7, 31, -33, 0, 32, -23, 46, 22, 22, -9, -7, -9, -12, -30, 36, -45, -16, 1, 31, -27, 3, 24, 30, -52, 21, -12, 1, -13, 26, -4, -46, -26, 34, 54, 30, -37, 1, -42, -21, -14, -7, 4, -9, -24, -3, -49, -13, -10, 11, -11, -13, -18, 1, -45, -9, 18, -21, 2, -38, 32, -1, -19, 13, 2, -46, -19, 6, 17, -25, 15, -29, -11, 21, -36, 37, -30, 24, -15, 45, -42, 27, 13, -3, -13, 9, -17, -6, 20, 33, 19, -20, -33, 1, -20, 35, 6, 2, -7, -22, 23, -37, -67, -10, -17, 46, -31, 26, 16, -18, 4, 41, -23, -43, -13, -5, -9, -43, 9, -57, 13, 55, 61, -5, -4, 2, -7, -57, 20, -23, -10, 49, -10, -22, 25, -4, -31, 5, -10, -32, 15, -5, -26, 4, -20, 3, -59, -7, -13, -5, -27, 25, -21, -63, 27, -25, -26, 2, -50, 17, -8, -38, 4, -9, -12, -15, 26, -13, 25, -2, -6, -8, 4, -23, -20, -51, 42, 2, 61, -41, -3, 39, 19, 11, -11, 4, 56, 16, 11, -10, -28, -28, -1, -28, 8, -34, -62, -5, -16, -8, 35, 39, 11, 20, -53, 11, 55, 8, 8, -7, -3, 8, 27, 15, -5, -1, 47, 31, 19, 9, 46, -47, -17, 40, -17, 1, 22, 4, 14, 5, -47, 10, -18, -6, -38, 11, -1, -33, 8, -5, -60, -17, -46, -32, -13, 25, -33, -54, 13, -15, -18, 13, -12, 3, 10, -2, 5, -7, 31, -17, -9, 13, -36, -3, 2, -29, 12, 11, -10, 31, -49, 38, -9, -32, 8, -18, -56, -14, 27, 3, 34, 23, 19, -19, 23, -11, 18, -18, 0, 18, 0, 6, 17, 21, -24, -3, -24, -21, -18, -51, -1, 15, 24, -13, -11, 32, -33, -25, -55, 26, 20, -16, -23, -35, -26, -9, -1, -40, -8, -36, -49, 11, 20, 30, 0, -54, -5, 39, 27, 7, 19, -60, 16, -23, -24, 8, 88, 13, 0, 36, 21, -25, -17, -3, 28, 9, -4, -42, -17, -17, 3, 18, -30, 2, 42, -7, 26, 3, 46, -41, -11, -16, -6, -42, -21, -24, 4, 23, 13, 41, 32, -20, 10, 29, 7, -20, -18, 33, -26, 17, -93, -23, -9, -29, 57, -52, 1, -26, 0, 24, -36, 23, 2, -4, -10, 54, -21, 12, -13, -1, 1, -36, -2, 28, -11, 3, -31, 26, -43, 47, 14, -14, -17, -7, 3, 8, -5, -15, 30, 22, 34, 25, 18, 13, -20, 22, 22, 24, 21, 50, -40, 8, 28, -48, 5, -3, 41, -25, 33, 29, -6, 15, 5, 12, 16, -15, -15, 29, 2, 4, 11, 19, -9, -21, -39, -24, 35, 28, 9, -1, -32, -16, -19, -6, -7, -9, 4, 20, -28, -7, -16, 24, 0, 49, 1, 46, -46, 32, -3, -26, -1, -19, -22, -1, 32, 37, 0, -11, -30, -22, 21, -17, -20, 14, 3, -7, 36, 9, -17, -22, 5, -56, 11, -4, -42, 9, 11, -20, 9, 28, -29, 7, -10, -1, 16, -9, 23, 11, -19, 22, 15, 3, -29, 5, -15, 15, -27, -22, 2, -37, -19, -7, -32, 30, -13, 20, -28, -11, -8, 20, -4, 26, -13, -24, -20, 30, -14, 8, 36, 48, 16, -9, 23, -43, 37, -14, 20, 36, 5, -14, 52, 10, -45, -11, -37, -29, -9, 4, -32, -1, -4, -31, 35, -18, -19, -25, -26, -38, 37, -18, -11, -25, 0, -20, -18, -36, -14, -25, 20, 41, -18, 16, 14, -17, 32, 7, 6, -36, -13, -3, 3, 0, 26, 18, -30, -11, -36, -29, -12, -10, -34, -1, 17, 24, 19, 11, -7, -13, -27, -49, -13, 16, 41, 18, 40, 26, 23, 34, -22, -7, -38, -15, 8, 29, 25, 68, -19, 2, -21, -11, 15, -29, -8, 5, -14, -26, -8, -26, -38, 12, 12, 3, -66, -15, 21, 50, -7, 45, 21, 11, 5, 7, -50, -44, -12, 20, -34, 8, -32, 4, 2, 9, -18, -22, -3, -19, -9, -13, -7, 24, 1, 35, -18, -11, 43, -26, -18, -30, -33, -1, 14, 16, 9, 29, -12, -45, 27, -28, 11, -10, -6, -36, 47, -11, -23, 5, 10, -48, 30, -8, 1, 34, 15, -12, 14, -52, 19, 26, 5, 0, -21, -27, -74, -40, -29, -32, -50, -5, 36, 32, -35, -10, 16, -23, -38, 3, -22, 18, 11, -41, 26, -21, 1, 2, -21, 7, 36, -35, -27, 0, 46, 5, -4, 8, 6, 33, -18, 18, 27, -68, 23, -49, -3, 26, 7, 15, 1, 28, 11, 8, 31, 28, -40, -5, 33, 14, 37, -13, -28, -7, 25, -3, 8, -53, 9, -4, -57, 1, 34, -41, 11, 35, 6, 11, -51, -8, -8, -6, 35, -10, -23, 18, -42, -26, 32, -8, -9, -12, -58, -22, -10, 3, 12, -18, -9, -10, -27, 20, 32, -33, 11, -14, 12, -18, 36, -57, 29, 4, -50, 39, -24, -14, 38, -8, 18, -8, 37, -40, -12, -14, 14, 30, -34, 25, -12, 19, 52, 12, -16, 8, -3, -3, 55, 25, 24, 12, -21, 0, -34, 1, -29, 7, -18, -2, -54, 26, -11, -9, 18, 4, 13, 48, -28, -32, 22, 7, -1, -23, -24, 41, 44, 32, 17, -13, -34, 6, -3, -42, -30, -23, -39, 19, -64, 36, 23, -40, 19, -35, -3, 23, -39, 5, 52, -3, -8, 24, -44, 11, 10, 32, 18, -44, -16, 41, 50, 5, 0, -14, -25, -33, -24, 12, -16, -22, 23, 36, -3, -5, -13, -19, -14, -1, 45, 15, -2, 24, -22, -58, -53, -15, -46, 16, 7, -52, -13, -7, 1, 47, 13, -30, -17, -10, 23, 14, 35, 26, 13, -11, 10, 11, 17, -3, -8, 7, -15, -12, 4, 6, 5, -11, -8, -49, 23, -12, 9, -6, 7, -1, -47, 19, 11, 9, -5, 45, -46, -43, -21, 10, 42, 37, -18, 53, -1, 9, -46, -14, 19, 16, 32, -10, 18, 32, 7, 29, -65, -19, -18, 30, -26, -9, 32, -5, 37, -13, 14, -33, -28, -9, 20, -31, 10, 8, -35, 29, 11, -4, 17, -1, -22, -33, 45, 22, -20, -5, 1, 13, -9, -24, -32, 29, -40, 9, -4, -32, 24, -30, -9, 19, -17, -3, -3, 19, -13, -26, -38, -32, -7, 30, -26, 21, 30, -3, 48, -29, 43, -29, 17, 7, 61, 21, -10, 7, -5, -29, 28, 40, 5, -5, 11, -41, 1, -34, -20, 35, -26, 5, -17, -18, -31, -9, -6, -23, 18, 20, -14, -29, 14, -33, -28, -53, 36, -46, 37, 22, -7, 26, 0, 22, 3, 10, -54, -20, -16, 22, 14, 55, 34, -26, -23, -15, -65, 7, -16, -23, 14, -1, -40, 0, -12, -59, 3, 11, 15, 33, 39, 16, 3, -47, 36, 34, 9, -5, 4, 2, 15, -3, 25, -9, 32, -46, 41, -12, 6, 9, 28, -54, 19, -5, -1, -12, -40, -39, -6, 16, -44, -22, 24, 30, 14, -25, 20, -32, 1, 34, 10, 13, 3, 21, -43, 24, -9, -20, 17, 3, 5, 5, 3, 26, -8, -21, -39, 8, -53, -25, -12, -68, -1, 10, -1, 9, -40, 38, 33, -1, -53, 11, -21, 9, 2, -20, 14, 24, 47, 26, -7, -27, 15, 51, -42, 33, 1, 10, 49, 17, -21, -61, 12, 4, -24, -1, -6, 10, 0, 19, 40, -10, -24, -6, 13, -33, 23, 35, -7, -103, -15, -14, -13, 38, -20, -34, -24, 13, 37, -10, -3, 26, -37, -1, 32, -1, -32, -31, 41, -29, -19, -3, 10, 25, -17, 24, -34, -7, -23, -8, 16, 0, 25, 51, 22, 33, 8, 19, -12, -11, 32, 0, -17, 15, -11, -13, 6, 17, -57, -13, 29, 15, 20, 50, 9, 39, -18, -41, -32, 23, -38, -7, -19, 7, -25, 16, 35, -34, 2, 4, -36, -8, -30, 30, 1, -87, -16, 13, 36, -23, -8, -5, 5, -7, -30, -4, -16, -8, 13, 9, -10, -11, 18, -24, -12, -23, 15, 13, -31, -9, -37, -9, 8, -2, -8, 37, 1, 64, -6, 23, -3, -12, -25, -9, -17, 0, -47, 32, -42, 10, 35, 42, -68, 15, 31, -39, 5, 6, 0, 19, 45, -17, 26, -17, -35, -3, 18, -10, -14, -22, -12, -55, -1, -24, -57, -59, 37, -39, -11, -1, -19, -56, -19, 9, 13, 14, 17, -73, -24, 15, 32, -28, 33, -42, -30, 16, -10, -1, -74, 15, -13, -6, 6, 25, -13, -19, 8, 0, -8, -27, 61, -46, 3, -44, 35, -27, -15, 15, 35, -22, -11, 0, -29, 8, 46, 40, 17, 0, -18, -10, -39, 12, 17, 9, 3, -4, 4, 15, -9, -17, 6, 11, -31, -51, -6, 19, -39, 3, -30, -8, -32, 8, 12, 6, -42, -42, -18, 45, 35, -44, -13, -32, -58, -22, 13, 22, 4, 2, -17, -62, -15, 20, 36, 4, 14, -27, 7, 10, -38, 15, 5, -41, 7, 15, 20, -12, -35, 17, 20, 38, 13, 19, -50, 3, 25, 1, -13, 30, 38, 25, -11, 10, 37, -51, 15, -29, -19, 29, 13, -40, -41, 28, -25, -6, 11, -22, 23, 29, -17, 10, -20, 15, -44, -23, -31, 1, 3, 11, -21, -16, -16, -48, 48, 0, 11, 10, 19, -5, 12, 9, 35, 28, 29, 41, 13, -15, -15, 11, 37, 14, -21, -9, 12, -21, 5, 28, 59, 37, -41, 3, -25, -18, -16, 22, -59, -40, 8, 1, 24, -9, 6, -62, 22, -42, -23, -17, -24, 24, 20, -16, 16, -4, 7, 35, 30, 36, 45, -4, 23, 1, 19, 21, 37, -15, 2, 11, -4, 17, 30, -40, 5, 4, 27, 28, -3, 2, -39, 60, -11, -18, -29, -36, -6, 39, -21, 27, 33, 12, 0, -25, -14, -21, -67, 27, -7, 20, -18, 4, 11, 2, -27, -12, -15, -25, -4, -29, -27, 8, 32, -41, -9, -4, 11, 6, 18, 6, -20, 31, -24, -35, -22, -7, -6, 38, -14, -27, -51, -8, 6, -12, -28, -25, -13, -22, 12, 40, -15, 6, 25, -15, -31, -21, -3, -1, 5, -12, -10, -13, -39, 28, 2, 49, 2, 37, 1, -10, -4, 11, 4, 3, -39, -31, -18, 10, 37, 12, 9, 50, 7, 25, 16, -27, -16, -1, -33, 7, -28, 17, 26, 14, -41, 6, -7, -50, 11, -3, 33, -13, 5, 11, 31, -25, 16, -9, 8, -18, 21, 25, 26, 4, -19, 36, 5, -9, -39, -44, -11, -32, -50, -4, 4, 16, -22, -2, 53, -23, 3, 6, 9, 1, -27, -12, -4, 5, -22, -28, -19, 2, -26, 0, 4, 9, 38, -5, -35, 5, -52, 42, -17, -21, 14, 6, 27, 38, 23, -32, 28, 0, -2, -6, 6, -15, 15, -3, 26, -55, 2, 1, 10, 17, -5, 11, -12, 44, -28, 15, -15, -23, -30, 1, 16, 0, -14, -31, 34, 51, -31, 3, -1, 6, -11, 7, -29, -23, -38, -31, 22, 10, 42, 0, -80, 27, -13, -29, 27, -32, 23, 42, -13, 18, 5, -13, 33, -7, 0, -5, -11, 21, 20, 35, 45, -65, 22, -20, -23, -36, -33, -3, -23, -24, -29, 19, -7, 20, -10, -2, -33, 0, -34, -4, 41, -16, 23, 32, 1, 40, 62, 35, 28, 5, 28, -14, 14, 14, -7, 44, -11, 15, -19, -5, -11, -11, 17, -59, -29, -33, 63, -37, -32, -21, -1, 21, -54, -2, 32, -17, 26, -2, 14, 1, 8, -3, -29, -26, -37, -6, 10, 5, -12, -33, -27, 51, 29, 44, -17, -41, -18, -24, 17, -41, -36, -24, -75, -1, 39, -12, 19, 29, -13, 36, 7, -25, 18, 17, 0, 1, 37, -8, -19, -23, -17, -3, 6, 54, 35, -31, 16, 13, -13, -2, 54, -19, 26, -32, 2, -20, -5, -51, -9, 23, -7, -27, -9, -14, -8, 3, 43, -2, -38, 18, 3, -24, -32, 13, 0, 25, 3, 30, 31, -4, 9, -42, -37, 43, -58, -43, 2, -17, -10, -21, 37, 17, 19, 23, -4, -17, 15, -18, 20, -14, 6, 4, -5, 29, -39, -50, -4, -11, -13, -14, -49, -19, 26, 16, 23, -8, 9, -6, -16, -23, -44, 28, -5, -20, 5, -44, -16, 32, -10, -4, -47, -25, -10, -24, 16, 10, -21, -12, -33, -11, -25, 17, -16, -26, -6, 9, 24, -4, 14, 16, -25, 2, 19, 17, 18, -10, -13, -2, 22, 26, -22, -17, 24, 34, -19, 46, 5, 18, -15, 9, 7, -3, -9, 1, -10, 5, 48, -28, 16, -60, -8, -12, -35, -34, -18, 0, -8, 36, -36, 28, -6, 16, -1, -31, -33, 17, 2, 1, 8, 6, -35, -3, 22, 18, -5, -13, -40, -41, 35, 27, 23, -32, 22, 33, -50, -1, 42, 1, 28, 11, 4, 12, 12, 20, -14, -44, -39, 2, 3, -14, -55, -29, 18, -50, -15, 16, 26, -1, 38, -11, 24, 12, -32, -28, 16, 3, 6, 16, 19, -58, 22, 20, 12, -17, -4, -18, 43, 2, -48, 4, -41, -4, -59, 9, 0, -63, 10, -13, 9, -20, -19, 43, -12, -12, 21, -13, -40, 42, -33, 22, 8, 6, -48, -40, -10, 9, 9, 15, 9, 7, 26, -16, -10, -11, -4, -42, -20, -18, 29, -44, -7, -35, 5, -23, 10, -36, -12, 23, 17, -19, -38, -25, -61, -19, 6, 43, 21, -21, 2, 16, -4, 7, 29, -25, 15, -28, -20, -68, -61, 6, -48, 28, 4, 32, 17, -8, -44, -40, 3, -8, 14, -54, 17, -41, -3, 38, 22, 1, 23, 13, 26, -3, 42, 4, -17, 38, 7, 0, -51, 19, -9, -5, -31, 0, 20, -3, -6, 9, -5, -4, 31, -21, -17, -21, -5, 12, 30, -2, -4, 45, 14, 45, -26, 30, 24, 33, 12, -42, -45, -13, -24, 0, 19, -24, -20, 11, 7, 21, 4, -7, -26, 10, -5, -22, 7, -17, 28, -42, -39, -6, 10, -42, -23, -15, 5, -25, -19, -11, -29, 0, -29, -2, 13, 21, 13, 10, 25, 1, 15, -4, -43, 53, 38, 19, -28, 27, 11, 44, 5, -23, -2, -19, -24, -19, 26, -3, 44, 29, 38, -8, -12, 9, -11, 35, 26, 19, -41, 36, 13, -6, -22, 47, -42, 1, -30, -30, 8, 21, 28, 3, -12, -15, 16, -6, -1, 8, 11, 37, -5, 5, -22, 9, -24, -45, -46, 16, 10, -23, 36, 8, -33, -21, -24, 8, 9, -10, 38, 10, -54, -22, 15, 0, 13, -8, -19, -31, -43, 38, 31, -41, 14, -29, 18, -12, -31, 13, 53, -19, 18, 27, -54, -55, 9, 18, -1, -16, -34, 21, 32, 16, 31, -19, 23, -35, -7, -7, 19, -30, -1, -40, -17, 23, 16, 3, -13, -3, 42, 17, -10, -5, 31, -66, 32, 12, 33, 3, 21, -20, -13, 22, 13, 4, 25, 6, 22, -31, 30, 29, 9, 58, -24, -16, -27, -1, -3, 15, 6, 10, 18, -37, 8, -33, 1, -10, -9, 9, 39, 9, -25, -25, 9, -27, -21, 4, 2, -6, -62, 33, -7, -53, -16, 36, 22, -19, 47, 34, -14, 13, -13, -23, -18, -12, 14, 9, 10, 22, -3, -51, -19, 24, -6, 0, -11, -14, -36, -5, 4, 1, 20, 37, 55, -5, -14, -14, 5, 1, 25, -38, 6, -7, -13, 70, 2, -7, -8, -44, 40, -33, 54, 1, 21, -7, 24, -16, 24, -26, 1, -6, 28, -14, 47, -33, 32, -48, -38, 34, 64, 9, 12, 25, 15, -30, -23, -19, 4, 35, -10, 7, -39, 3, 14, 18, 43, 7, 32, 24, 30, -2, 20, -5, 23, -25, -29, -14, 4, 10, -62, -33, -16, -29, 26, -35, -25, -9, -18, -12, 7, -35, 9, -23, -4, 23, 32, -42, 15, -21, -25, -32, -34, -29, -20, -40, 34, 25, 21, -20, -18, 31, 7, 26, -20, -13, -33, -3, 8, 29, -33, 34, 49, 7, -42, -22, 24, -15, 3, -2, 24, -2, -8, -12, -19, 28, 21, -1, -53, 3, 2, -7, -24, 21, 38, -11, -28, -8, -38, -39, 18, -39, -26, 5, -50, 7, -20, 27, -6, 19, -23, -13, -38, 1, -6, 33, 19, -23, 37, 8, -8, 4, 6, -4, -32, -13, 34, -8, -23, 19, 41, -23, -39, -35, -6, -1, 10, 22, 30, 60, -22, -10, 20, -45, 44, -21, -52, -6, -5, -18, 27, -5, -39, 26, -6, -47, 21, 53, -49, -7, -1, 21, -51, 10, -10, 16, -38, -27, 8, 22, -7, -17, 33, 28, -42, -14, 0, 27, -33, 10, 13, -11, -3, 38, 37, -9, 17, 7, -3, 2, -8, -10, -52, 35, -2, -19, -42, -39, 6, 7, 12, 20, -8, -32, 5, 16, -16, -29, -5, 6, -16, -33, 10, 5, -3, 2, 16, 4, 18, 1, -24, 0, 3, -32, -8, 34, 47, 11, 22, 34, -45, 7, 20, -22, -39, -29, 35, 11, -61, -27, 21, -43, 28, -20, -35, -2, 14, -46, -28, 18, 48, 23, 12, -16, -2, -6, -3, 36, -35, 30, -36, -19, -26, 44, -40, 27, 27, 33, -9, 19, 30, -30, -26, 3, -28, -11, -29, -14, 31, 51, 62, -18, 21, -1, 5, -1, -17, -35, 17, 6, 9, 22, -6, -18, 30, 25, -34, -4, 24, 22, 3, 27, -29, 1, -8, 21, -28, 2, 2, 36, 13, 9, 16, -41, 7, -5, -22, -13, 15, 1, -6, -27, -48, -16, -22, 3, -34, -43, -22, 4, 7, -44, 44, 2, -22, -25, -41, 20, -11, 12, -17, -11, 31, -21, 22, -13, -14, -63, -8, -31, -3, -18, 5, -24, -25, 33, -18, -10, -23, -8, 42, -51, -11, 34, 14, -2, 23, -47, 19, 4, -10, -10, -24, 10, 4, 43, -21, 14, -15, -5, 23, 5, 18, 17, -16, 26, 18, -1, -35, -10, 29, -16, 22, 0, 37, 27, 1, 5, -9, 6, -13, 28, 33, 44, -57, -29, -26, -1, 1, -10, 5, -18, 43, 42, -2, 32, -9, 27, 17, 17, 12, -42, 41, 35, -15, -5, 11, -28, 25, 2, 27, 17, -7, 38, -12, -5, 44, 5, 21, 36, 6, 27, -4, -3, -21, 4, -24, 37, 14, 13, 2, -19, 0, 14, -23, 10, -24, 17, 14, -10, -1, 13, 25, -31, 0, 2, -7, 33, -6, 24, -22, -16, 8, -16, 11, -3, -19, -17, -14, 0, -25, 31, -17, 28, 31, 43, 13, -48, -29, 0, -5, -42, -8, 0, -20, 7, -34, -16, -36, 34, 13, -1, 16, 42, 8, -3, 53, -1, -5, 2, -30, 18, 16, -17, 4, 11, 6, 5, 20, 21, 32, -3, 28, -24, -7, -4, -5, 27, -8, -24, -20, 29, 0, 13, 23, -12, -5, 20, 26, -18, -18, -46, -9, -39, 0, 15, 21, 11, -8, -26, -18, -31, -7, -42, -22, 7, 17, 31, -5, -27, -11, 31, 36, 16, -2, 36, 8, 13, 5, 21, 8, -5, 38, -19, 22, 29, 46, -5, -15, -18, -20, 21, 10, 7, -1, -19, 36, 40, 21, -7, 1, 4, 40, 31, 11, 21, 33, -25, 11, 17, -40, -10, -43, 42, -21, 22, -34, 3, 30, 23, -17, -48, -20, -14, 12, 0, -8, 5, -18, 24, -33, 34, -33, -14, -1, -23, 22, 39, -24, 35, -21, 12, -4, 26, 5, 34, 1, -38, 17, -39, 28, -20, 21, -40, -11, 22, 39, -16, -28, 17, 16, -5, 2, -30, -6, 8, -6, 16, -18, -19, 0, -6, 5, -8, -35, -18, -32, 17, 15, -19, 2, -10, -12, 0, 31, -36, 49, 47, -25, -40, -41, -12, 23, -9, -26, 49, 33, 14, -13, -20, -26, -22, 64, 8, 0, -20, 22, 32, -7, 23, -17, -16, -8, -4, 42, -12, -48, 1, 25, 22, -27, 26, 45, 14, 12, 19, -27, 34, 24, 19, -21, 0, -27, -4, -12, -18, 5, -1, 42, 31, -44, -25, 11, -26, 17, 21, -21, -13, 16, -31, 13, 6, 20, -21, 1, 39, 35, 37, 19, 18, 13, -25, 17, -41, 9, 11, 20, -13, -25, -5, 8, -9, 8, -5, 5, -12, -1, -23, -47, 36, 12, 16, 19, 18, -14, -6, -37, 15, 0, 18, 23, 35, 30, -54, -4, -22, -36, 5, -6, -1, 10, -48, 0, -32, 26, -42, -1, -10, -24, -39, 5, -24, 18, 25, 0, 7, -12, -23, 29, -30, 9, 33, 10, 10, 6, 22, 7, 26, -16, 11, -54, -7, -31, 4, -7, 5, -22, -4, 17, -22, -13, 31, 33, -3, 25, 57, -17, 24, -49, 2, -24, 39, 5, 45, 24, 14, 43, 6, 43, 40, -11, 35, 8, -9, -36, -46, -1, -35, -63, -16, 18, -38, 26, -41, 27, -5, -2, 19, 45, 38, 13, 19, -9, -24, -15, 36, 3, 27, -41, -75, -12, 20, 30, -7, -10, -22, -55, -34, 5, 27, 5, -36, -69, -32, 19, -20, -40, 42, -12, 21, -3, -10, 35, 8, 1, -38, 23, 0, -51, -28, 11, 17, 30, -30, 28, -9, -27, 33, 4, -61, -6, 2, 0, -33, 37, -39, 24, 2, -37, -17, 4, -41, -14, -21, 11, -32, -8, -29, 8, 10, 13, 9, -10, 27, 44, -1, -2, 2, -17, 16, 2, -26, -21, -30, -42, -66, -14, -44, -10, 32, 4, 16, -25, -7, 24, 23, -41, -21, -7, -27, -40, -44, 4, -2, -15, 5, 2, 4, 72, -28, 28, -51, -24, 34, -20, -28, -30, 2, 22, -18, 7, -16, 35, 20, -27, 21, 9, 14, -18, -12, 5, -34, -24, 45, 1, 36, 59, 1, -42, 34, 9, 52, 20, -1, -21, -71, 28, -33, -12, -42, 36, -22, -3, -27, 0, 12, -19, -49, 46, 2, -28, 18, 33, -20, 37, 9, 36, -58, 28, 21, 60, 21, -14, 19, 39, -56, -22, -36, 45, -25, -56, 42, -18, -1, -40, -10, -10, -31, -45, -47, -2, -18, 29, -12, -16, -14, 28, 2, 39, 5, -7, -11, 11, -49, 22, 25, -15, -27, -41, -44, -14, -2, -44, 40, -45, -17, 39, -16, -32, -2, 30, 22, -16, -47, 18, 39, 12, 10, 5, -33, 47, -14, 5, -17, 30, 30, -30, 21, -56, 2, 6, -65, 7, -30, -28, 15, 16, -15, 10, 50, 13, 2, 10, -14, -25, 22, 8, -7, 29, 35, 24, 7, -1, 43, -29, 35, 23, -42, 52, 26, -27, -36, 6, 1, 31, 43, 10, -27, -16, -45, 31, 58, 1, 35, 11, 30, 22, -1, 1, -5, 13, -46, -29, 12, 8, -7, 4, -44, -46, 14, -7, 17, 2, 8, -21, 7, -10, -32, -22, -3, 44, 18, 1, -31, 30, -42, 43, -32, -1, -16, -19, -43, -17, -15, 20, 23, -54, -44, 33, 10, 17, -22, -11, -10, -20, -25, -15, 3, -26, 44, -8, -16, -61, 6, -20, -24, -9, 27, -50, -36, 0, -9, 43, -20, 5, -28, 25, -30, -20, 44, -65, 33, 1, -33, -15, 39, -5, -18, 15, -42, 1, -31, 12, -6, 23, -1, -31, 13, -37, 5, 22, 23, 44, -13, 21, 45, -42, 25, 37, -42, -32, 18, 39, 7, -26, -24, 28, 12, 24, 32, 9, -15, 13, -25, -25, 8, -37, -22, 37, -6, 26, 24, -7, -15, -13, 41, -24, -30, 23, 4, -26, -21, -25, -11, 25, -15, 39, 37, 12, -12, -30, -23, 4, 1, 40, 13, -16, -11, 8, 6, 26, 21, 24, 28, 41, -7, 2, -11, 32, -46, -7, 25, -10, -3, 40, 23, -34, -2, 14, -4, -19, 35, -45, -33, 17, -13, 19, -10, 29, 11, -26, 5, -31, 11, 12, -10, -19, -24, 17, 35, 29, -41, 9, -48, -3, 7, 51, -9, -26, 17, 4, -35, 14, 36, 45, 35, 1, -22, 29, 27, 38, -20, -18, 6, 44, -26, -20, 14, 18, -25, 8, -26, 28, -21, 22, 7, 6, -25, 36, -1, 0, -28, -20, 2, 13, -3, -9, -32, 14, -18, 26, -41, -36, -36, 5, -44, 22, 12, 16, 18, 24, 1, 24, -19, 31, -2, -46, -2, 22, 25, 20, 10, 11, -10, 2, 2, -17, 29, 10, 8, -40, -25, -9, 30, 53, 34, 9, 5, 32, -30, 12, -35, -29, -11, 20, 9, 31, -13, 8, 27, 39, -23, 5, -25, 13, 46, 34, 1, -17, 0, -33, 40, -20, 10, 21, -34, -25, -17, -4, 21, -3, -2, 18, 14, 13, 23, -10, -18, 0, -35, -25, -66, -3, 31, 10, -43, 28, 26, -43, -26, -11, 6, -14, 20, 1, 46, 29, 51, 10, -10, -23, -4, -22, -32, -22, -38, 41, -11, -31, 26, -12, -15, 55, -44, -35, -3, 25, 7, 0, -40, 39, -41, 25, 29, 9, -14, -39, 8, 7, 4, 2, 23, -33, -1, 33, -11, 39, 38, -26, -9, -39, 6, -21, -22, -11, -44, -16, -9, -44, -34, -1, -4, -2, 33, -22, 40, -9, 22, -5, -28, 11, 8, -28, -27, -4, 28, 35, 6, -42, -2, -5, -58, 10, 29, -11, -42, -27, 24, 49, -20, 10, 5, -38, 10, -8, 6, -47, 16, -24, -18, -8, 34, -15, 28, -2, -15, -3, -9, -44, 6, 21, 15, -24, -52, -42, -14, -28, 17, -34, -18, 18, 27, 7, -5, -33, 13, 0, 2, -21, -4, -39, -4, -14, -19, 16, -17, -29, 28, 62, 11, 13, -18, -3, 28, -29, -41, 29, -32, -16, -11, -16, 4, 23, 10, -41, -17, 14, 31, -41, 25, -6, -10, -24, -41, 11, 28, -34, -27, 25, -24, -21, 51, 4, -26, -7, 29, -43, -20, 8, 41, -20, 21, -23, 15, 35, 0, -21, 38, 19, 15, 10, 23, 55, 10, 54, 5, 13, -27, -40, 27, -30, 18, -10, -17, 9, -40, -19, -17, -29, 40, 24, -5, 1, -19, -49, -16, -8, 5, -17, 35, -21, 0, 8, -10, 10, -12, 11, -39, 9, 14, -6, 15, -25, -35, 9, 8, -42, -50, 19, 17, 16, 38, 21, -35, 16, 12, 3, 29, 10, -54, 20, 7, 16, 36, 17, 19, -23, -5, -5, -35, 12, -9, -14, -8, -3, 33, 32, 41, -7, -13, -21, 15, -36, -16, -43, -63, -58, 31, -24, -22, -19, -24, 2, 48, -4, 14, -29, 8, -35, -36, 39, -39, -63, 8, -60, -11, -24, -29, 22, -27, -4, -54, -28, 35, -27, -12, -21, -9, 8, -36, -18, -7, -4, -39, 3, 2, -3, -12, -30, 33, -25, 29, 37, -3, -28, -10, -38, -17, 13, -34, 45, 10, -26, 34, -29, -33, 7, -47, 31, 7, 20, -31, -38, 24, 40, -22, -15, -8, 16, -1, -18, 25, -17, 20, 52, 2, -19, -33, 38, -6, 21, -31, -66, 63, -30, -29, 10, -22, 20, 28, -40, -15, 3, -11, 17, 28, -17, 19, -32, -1, -6, -25, -47, 61, 32, -12, 13, -21, -31, 43, -33, 6, 88, -11, 4, -30, 9, -14, -20, 48, -38, -7, 38, 24, 47, -15, -30, 25, 51, -18, -22, -41, -17, -45, -20, 22, -14, 23, -2, -23, -16, -14, -68, 23, 13, 53, 19, -26, 32, 9, 16, 16, -37, 45, -14, 4, -3, -52, 10, -34, -32, 7, -14, 8, -4, -43, -10, -24, 16, -21, -9, -1, -21, 5, -25, -17, -34, 26, 51, 2, -40, -29, 13, 2, 26, 22, 9, 14, 27, 2, 3, -28, -52, -7, -3, -15, -45, -55, -5, -24, -2, 24, -11, -18, 27, -23, -44, 14, -11, -11, -32, -15, -33, 34, 11, -1, -17, -14, -17, -43, -35, 19, 0, -12, -10, -15, 19, -5, 19, -36, -16, 23, 16, -37, 30, 13, -40, -14, -17, 17, -14, 25, 1, 33, 15, 14, 3, 24, 43, -7, -8, 30, -10, -52, -49, -7, 10, 44, -41, -55, 41, 14, 46, 21, -32, -33, 38, -24, -50, -5, 11, -22, 11, -29, 31, -38, -20, -40, -11, -6, 8, 6, -47, -14, -35, 21, 17, 33, -1, -29, -76, -43, -9, 22, 27, -4, -7, -18, 10, -19, -21, -24, 32, 26, 28, 5, 0, -4, -9, 9, -34, -30, 16, -33, -23, 33, -14, 10, 22, 49, 7, 11, -22, 0, 17, 31, -15, 24, 19, -22, -29, 11, -19, -18, -36, -27, 8, -42, 31, -20, -17, 11, 30, -2, 11, -25, -14, 42, -1, -28, -9, 6, -1, 0, 4, -56, 18, -17, -34, -23, 19, -12, 38, 11, 10, -21, -17, 37, 42, 1, -12, 13, -14, 12, 33, -12, -12, 16, -9, 3, 19, -34, -19, -16, -13, -6, -24, -33, -27, -38, -13, 0, -12, 18, 36, 34, 12, 21, 27, -5, 23, 3, 36, -18, -8, 26, 10, 51, 38, -30, 12, -20, -26, 25, 25, -1, -5, 25, -9, -7, -18, 18, 14, 30, -22, -40, -15, 11, -3, 34, 20, 32, 14, 46, 50, 26, 3, 6, -41, 24, 27, -35, 51, -15, -35, -3, -24, -6, 8, 11, 30, 1, -26, 16, -12, -16, 21, -3, -41, -44, 9, 8, 19, -28, -16, -37, 21, -29, -22, 10, 17, 2, 17, 31, -3, 23, -6, -7, 9, -3, -18, 22, -18, -4, -8, 27, -12, -12, 8, 2, 50, -19, 20, -36, -23, -31, 32, 10, -30, 20, -36, -14, 5, 8, -7, 15, 14, 6, -23, 2, 37, 1, -4, 11, -84, 24, -7, -2, 21, 30, -4, 2, -21, -28, -7, -25, -13, -44, -26, -17, 10, -13, 0, -35, 24, 25, -42, -10, 24, 0, 27, 6, 19, -48, 39, -21, 9, 54, -18, -16, 5, -21, 31, -12, 10, 44, -24, -8, -33, 5, -26, -37, -86, -20, 45, -28, 0, 29, -68, 9, 7, 29, 22, -28, 29, 15, -60, -11, 6, 26, 21, 14, -24, 52, 15, -9, 4, -36, 5, 27, -13, 11, -30, -2, -39, -31, 22, 12, 5, 20, -6, 2, -5, -40, -29, 42, 23, -32, -43, -56, 29, 4, -11, -11, -17, 24, -3, -46, 1, 39, -32, 14, -27, -67, -28, -17, -22, -4, 11, 14, -7, -4, -25, 40, 35, -3, -9, 38, -24, 35, -33, 11, -72, 14, -36, -9, 27, 2, -17, 18, -36, 6, -32, -35, -17, 42, -65, 6, 1, -38, 20, 41, -15, -14, -38, 7, -44, -1, 53, 29, -21, 13, 4, -24, -6, 19, 37, 40, 20, -45, -36, -14, 18, -3, 52, 0, 46, 33, -23, -5, 32, -26, 13, 9, -13, 2, 19, 7, -2, -6, 26, 8, -14, 2, 15, 29, -54, -42, 8, 15, -25, 6, -34, 1, -49, -31, -28, -18, 2, -31, 12, -23, -3, -41, -2, 54, -21, -3, -28, 32, -12, -2, -8, -51, -19, 38, 12, -4, -4, 4, 4, 30, 25, 28, 4, 34, 29, 20, 42, -14, -44, 8, 21, -1, 9, 42, 5, 29, -42, -8, -54, 0, -5, -18, -39, 10, -43, -20, -12, -4, -5, -40, -14, -34, 36, -23, 29, 3, 31, -18, -37, -49, -15, 34, -23, -13, -41, -26, -29, -33, 7, 11, 26, 6, 13, 1, 6, -3, 10, 6, -31, 21, -30, 25, 13, -2, 21, 9, 36, 22, -1, 43, 21, 6, 12, -18, 4, -27, -18, -6, 16, -13, -32, -5, 37, 11, -27, 23, -22, 0, 43, -19, 11, 7, -32, -17, -76, 3, 4, -17, -41, -75, 27, 13, -19, -33, 16, -28, -33, 33, -3, 15, -17, 16, 28, 18, 22, 7, -8, 25, -5, 33, 5, -12, 26, -20, -6, 55, 1, -57, -45, -19, 19, 27, 10, -8, -54, -60, -53, 35, 44, 30, -1, -1, -2, 17, -44, -20, -36, -11, 62, -51, -58, 13, 29, -13, -2, -24, 10, -20, -5, -25, 25, -22, 0, 1, -41, -18, -16, -30, -24, 35, 13, 41, -79, -31, -27, -28, -10, 31, 70, 7, 1, 38, -28, 9, -36, 2, 1, -10, -26, 15, -13, -12, -2, 16, 1, 30, -6, -18, 33, 4, 33, -16, -28, -20, -16, 0, -16, -4, -36, 12, -15, 14, -42, -28, 30, -32, 39, 23, 6, 7, -46, 28, 29, 23, 2, 5, -15, -15, -18, -28, -28, 27, 27, -12, -26, 23, 5, -7, 16, 9, 39, 15, 40, 12, 9, -4, 34, -4, 11, -18, -31, 29, -30, -3, -30, 4, -43, 5, -47, -44, 0, 38, -2, -22, 7, 4, -28, -26, -14, -28, 34, -20, 2, 20, -5, -28, -19, -2, -25, -14, -21, 6, 11, -35, -6, 10, -18, 13, 19, 21, 43, -12, 64, 27, 39, 35, -5, -35, 27, 21, -7, -29, 23, 32, -12, 8, -4, -60, -5, -17, -15, -17, -26, -29, -42, -30, 28, 15, 2, -45, 23, 3, -18, -12, 9, -12, -1, 18, -40, 16, -1, -54, -9, 68, -15, -72, 27, 8, 10, -1, 40, 1, 8, -3, -22, -3, 29, 30, 8, -8, 49, -7, -8, -16, 4, -33, 21, 3, 25, -13, 11, 10, -36, 19, 3, -26, -24, -37, 15, -15, -27, -1, 66, -29, 13, 64, -14, 14, -9, -7, -36, 22, 26, -14, -35, -12, -20, -24, 14, -9, -4, -17, 4, 19, 28, 8, 33, 4, 0, 31, 35, 12, -22, -31, -1, 18, -30, -27, -13, 5, -26, -7, -76, -36, -33, -8, -35, 53, 3, 32, 2, -46, -51, 7, 17, 41, -47, 0, 4, 0, 13, 23, 17, 1, -46, 6, 1, 6, -13, -14, 11, -16, 11, 17, -15, -34, 14, -16, -13, 28, -8, 49, -3, 0, -19, -13, 27, 35, 33, -1, 30, -36, 18, 69, 3, 20, -11, 27, -50, -11, 5, -14, 0, -28, 9, -8, -21, -45, -24, 9, 37, -40, 36, -23, 20, -8, 26, -8, 43, 2, 17, 36, -31, 7, 5, 38, 10, 43, -25, 15, -8, 9, -16, -11, -14, -30, -42, 16, 30, -38, 25, -9, -19, 10, 1, -6, 36, 42, 18, -12, 6, 24, -39, -37, -14, -14, -22, -45, -56, -18, 41, -30, -28, 17, -10, -33, -43, 9, 39, 9, 48, -2, 38, -26, -58, 29, 22, 35, -24, 23, -19, -19, -12, -7, -33, -33, 3, 19, -13, 20, -17, -5, -7, -4, 12, 12, 15, -24, 2, -1, 25, -8, -15, 20, -27, -29, 7, -17, 4, 1, 2, 27, 37, 30, 7, 32, -2, -31, 28, 35, -36, -25, -5, 24, 4, 11, 7, 30, 31, 11, 13, -12, 39, 33, 18, 16, 2, -14, 22, -4, 10, 15, -28, 1, 6, -10, -21, 6, 36, 5, 0, -31, 19, -24, -2, -8, 12, -33, 0, -43, 6, -3, 3, -15, -13, 3, 46, 53, 16, 57, 16, 10, -31, 64, -9, 23, -30, -20, -8, -46, -39, 24, -16, 35, -5, -38, 14, 2, 9, 0, 43, -8, -41, -11, -43, 34, 2, 33, -10, 25, 18, 7, 11, -11, 28, 9, 34, -1, -19, -8, 49, -25, 12, 15, -18, 20, -31, 13, -39, -26, -56, 21, -7, -12, 0, 4, 53, 39, 0, -16, 21, -62, 10, -19, 10, -23, -16, 1, 28, -42, -29, 7, 5, -19, 17, 4, -15, -13, -2, -19, -9, -23, 8, 46, 24, -6, 10, 1, 51, -44, -15, -34, -2, -11, 37, -35, -39, 32, 25, 14, -38, 1, 13, 43, -13, -34, -36, 15, -40, -3, 10, -22, -22, -30, -4, -5, 8, -21, -25, 15, -1, 8, -27, -12, -16, -29, 47, 45, 13, -20, -18, -32, 44, -2, -3, 11, 60, -13, -7, -12, -33, -43, -39, -38, 16, -21, 4, -33, -17, -36, 37, 19, 15, 3, -8, 18, 57, 12, -42, 1, 22, 3, -8, 11, -32, -35, -27, 41, -39, -26, 28, 14, 39, -5, 3, 30, -30, 0, 3, 9, -24, 25, 39, 4, -4, -22, 15, -21, -28, -43, 21, -27, -56, 29, -16, 14, 19, 42, 24, -30, -52, 7, 28, -18, -11, -4, -11, 18, -14, 19, 17, -12, 27, 21, 6, 8, 25, -43, -16, 2, 25, -15, -1, 2, -30, 2, -21, -18, 3, -5, -2, -4, -15, -12, -26, 44, 38, 35, -31, -10, 31, 41, 20, -11, 6, 7, 14, -15, 49, 10, -27, -7, 39, 22, -27, 8, 7, -10, 20, -10, -24, 1, 30, -13, -42, -8, -33, 8, -1, 10, 0, -24, -17, -55, 20, 35, 29, -18, -20, -48, -6, 14, -29, -46, -11, -6, -56, -9, 5, 42, 21, 2, -4, -16, -7, 63, -9, 3, 4, -45, 24, -3, 28, 18, 25, 39, 1, -14, -62, 5, 0, 16, 39, -13, 12, 53, 17, 6, -50, -3, 3, -23, 36, 45, 2, 2, -29, -18, 10, 0, 32, 18, 8, -14, -15, 28, -21, 39, 7, -32, 10, 25, -11, 7, 17, -35, -15, -2, 54, -43, -3, 0, 5, -37, -14, -6, -44, 9, 22, 18, -7, -12, 7, 25, 8, -52, 23, 1, -5, -16, -39, -24, -3, -1, -20, 6, -53, -6, 9, 16, -33, 7, 2, 6, -18, -40, 42, -27, 25, -36, -3, -4, -54, 17, 23, -37, -32, 1, 18, 23, 38, -5, 12, -16, -36, 2, 17, -41, -12, 16, 33, 12, 31, -11, 1, -1, -23, 38, 10, -56, 9, 46, -25, 15, -18, -35, 2, 4, -14, 1, 22, -29, 14, -9, 9, -30, -24, -24, 39, -2, -21, -41, 31, -5, -5, -3, 40, -82, -14, -37, -14, -10, -30, -17, 22, 17, 15, -50, -6, -50, -10, 39, -46, 5, -28, 30, -38, -81, 9, -25, -10, -21, 0, 34, 31, -39, -9, 3, 52, 29, 19, -24, -84, -11, 11, -23, 36, -30, 3, 24, -12, 10, 33, 18, -2, 9, -7, -5, 41, 11, 27, -3, 13, 5, 44, -4, 5, 48, -32, -55, -43, 31, -9, -35, 9, -7, 34, -18, -13, 4, -28, -16, -20, -13, 16, -20, -16, -41, 20, 35, -26, -20, 27, 69, 2, 34, -5, 4, -71, -15, -23, 10, -37, 1, -14, -7, 47, 37, -39, -5, -10, 42, -21, 43, 39, -21, -27, 21, -46, 37, -46, -38, -40, -6, 14, 16, 5, 4, 1, -13, 0, -17, 19, 11, 29, -12, 37, -9, -33, -21, 18, -4, -5, 27, 3, 30, -52, -11, -9, 16, 3, -37, -2, 2, 54, 51, 45, 18, 3, -16, 17, 18, -15, -10, -6, 8, 14, -23, 8, 19, -17, -22, -2, -37, 27, 24, -44, 2, 27, 1, 23, 49, -6, -42, 12, -12, 6, 15, 7, -44, -33, -26, 0, -33, -26, 23, 10, -17, 32, -11, -17, -20, -18, -7, 17, 27, 3, -9, 24, -29, -23, -37, -8, -4, 17, -22, -30, -12, 14, -42, -17, -22, -27, -3, 15, 5, 11, 11, -57, -30, 22, -58, -6, 11, -28, -63, 15, 15, 21, -12, -15, 4, -4, 32, 14, 37, -3, 21, -32, -5, -4, 10, 35, -23, -45, 25, 21, 36, 61, -5, 9, -2, -11, 26, -29, 11, 17, -22, -10, 43, -25, 16, -17, 9, 31, 11, -30, 34, -32, -17, 1, 33, -35, 36, 19, -23, 14, -5, -2, 18, -66, -3, -37, 5, -35, -1, 22, -28, -20, 5, 15, -23, -32, 43, -17, -12, -35, 22, -30, 4, -9, -24, -57, 18, -55, 47, -15, -38, -8, -4, -8, -16, -30, 20, 21, 12, -19, 13, -24, -5, 40, 3, -31, 21, -10, 19, -8, 43, -49, 7, 4, -4, 0, -16, -10, -33, -29, 49, 25, -49, 4, 3, 16, -36, 28, -13, -4, 5, 10, 31, -41, 11, 36, 15, -2, 21, 6, -13, 20, 5, -9, 15, -22, 14, -2, 5, 35, -14, 5, 22, 23, 6, 19, -1, -10, -27, 12, -19, -2, -4, 24, -34, -15, -6, -23, -15, -14, 10, 34, -12, -15, 19, -7, 10, 46, -3, 44, -29, -33, 19, -13, 12, 22, 40, -14, 18, 11, -22, 29, 19, -54, 17, -7, 13, 23, 2, -13, 0, -44, -29, 8, 19, -40, 24, -8, -10, 11, -43, 1, 33, 11, -7, -6, 0, 20, -14, 12, 28, 23, -54, 36, 42, 42, -7, 45, -40, -6, -11, -16, -23, -3, 39, 17, 3, 12, -14, 1, 26, -28, -28, -47, -12, 22, -20, 35, 0, 22, 2, -15, -5, -10, 3, -16, -18, 26, 13, -2, 12, 6, 23, 19, 33, -56, 18, 24, 9, -35, -14, -33, -14, 21, -13, 18, 6, -23, 49, 44, 5, -27, 21, -11, 11, -33, -13, -2, 9, -3, 23, -4, 14, -30, -4, 9, -26, -24, 33, -29, -20, 5, -18, -12, -13, -7, 12, 35, -42, -2, 28, -31, 13, 37, -6, -9, 33, -26, 46, 24, -3, 23, -12, 4, -27, -13, -13, 4, -15, 37, -10, -13, -4, 42, -1, -6, -46, 18, 39, 22, -55, -55, 8, -8, 22, 29, 25, 5, -43, 1, 42, -5, 6, -5, -2, -32, -29, -3, 9, -14, -4, 28, 28, 5, 25, -30, 47, 3, -80, -17, -13, 1, -9, 6, -4, 36, 29, 7, 27, -14, 20, 13, -15, 12, 39, -30, -34, -43, -6, -29, -43, 8, -34, -11, -24, -43, -10, -28, 27, -8, 22, 26, 17, 31, 12, -46, 4, -31, 18, 14, -10, -20, 1, -31, 11, -22, -6, 45, -3, 25, 42, 13, 37, -27, -30, -45, 5, 7, -6, -6, 13, -70, 4, 8, -37, -38, 46, 12, -8, -47, -7, 34, 17, 17, -5, -38, -21, -13, 53, -22, -26, 1, -16, -35, 7, -10, -8, 42, -35, 26, 9, -28, 47, 18, -38, 0, 18, -22, -45, 16, -23, -21, 39, -8, 33, 17, 62, -34, 5, 8, 30, 30, 19, -34, -2, -7, 45, -48, -91, 11, -57, -52, -22, 4, 48, 0, 13, 31, 30, 22, -15, 30, -13, 39, -1, -27, 35, -12, 17, 19, 3, -23, -57, 35, -26, 2, -49, -12, -9, -57, -34, -19, 32, 9, 5, -15, -9, -22, 46, 37, -15, 51, 2, 31, -5, -44, 41, -15, -14, -32, -31, -37, -1, -5, 20, 6, -32, -16, 18, 19, -57, -6, 2, 23, 21, -28, 16, 11, -11, 13, -26, 7, -16, -14, 13, -10, 12, -24, -17, -17, 11, 25, -18, -14, -32, -12, 27, 3, -25, 18, -6, -4, 27, 2, -14, 33, 31, -20, 22, -9, -36, 0, 3, 5, 31, -29, -60, 15, 17, 26, 13, 10, 21, -7, -50, -74, -38, 24, 25, 10, -25, 18, -15, -44, -26, -17, -30, -8, -39, 6, -6, -2, 2, -27, -22, -6, 25, 19, -32, 11, -29, -58, -16, 46, 25, 8, 34, 38, 11, -19, -14, -30, 1, -15, 36, 26, 39, -24, 26, -11, 61, 23, 5, -12, 0, 12, -4, 40, 13, -28, -64, -23, 7, 22, 27, 6, -34, -27, -9, -37, -14, -14, -12, -47, 9, -8, -34, -60, -13, 29, -16, 23, 19, -30, -28, 44, 23, -23, 0, 27, -29, 22, 18, -10, 12, -11, -17, -19, 6, 46, -42, 15, -18, -20, -32, -57, -12, -32, 0, -35, -16, -34, -35, -41, -20, -25, 3, -13, 19, 40, -24, 43, 7, -48, 16, 21, -25, -1, -49, 27, 40, -14, 18, 14, -68, -26, 27, 33, 20, -38, 21, -7, 26, -5, 29, -1, -12, 4, -2, -6, 14, -38, -3, -7, -7, -8, -11, 30, -7, -24, 36, 13, -18, 18, 19, -36, -16, 22, 43, -63, 4, 0, 12, -4, 41, -11, -14, -51, 14, -32, 8, -27, -20, 12, -9, -38, 42, -32, 24, -34, -3, -10, 26, -13, 25, -3, 13, -3, -7, -3, -33, 42, -27, 15, -5, -7, -8, 22, -5, 24, 35, -1, 35, 2, -36, 17, -59, -9, 18, 17, -42, 6, 22, -4, -22, -11, 13, 9, -12, -4, 27, 25, -4, 27, 36, 17, 4, 33, -13, -25, 68, -29, -50, 17, 17, -47, -26, -12, -40, 36, -32, -7, 31, 14, 11, 2, -10, -23, -30, 20, -8, -19, -37, -11, -35, -14, -3, 3, -29, 12, -15, 36, 18, 11, 34, 33, 4, 13, 15, -9, 21, 10, 14, 21, -4, -21, -32, 22, 10, -29, 2, -24, 33, -3, 47, 33, 19, -31, -32, -46, -30, -30, -25, -5, -7, 22, 7, -15, -5, 18, 6, -8, -42, 2, -20, -29, -12, 10, -32, -36, 18, 13, -27, -7, -13, 1, -1, 15, 18, 26, -14, -29, 29, -19, 22, 37, -23, -29, -17, -45, -19, 5, 28, 8, -32, 17, 1, 15, -15, -14, 38, -26, 44, 23, 22, -25, -13, -27, -30, -53, 21, -8, 50, 9, 29, -8, -22, 34, -41, -16, 18, -11, 33, 56, -9, 24, -46, -5, -48, 30, -29, 18, -6, 6, -29, 20, -32, 12, -42, 19, 2, -26, 37, 0, 15, -41, 19, -28, -9, -51, 34, -15, -20, 17, -46, -13, 50, -16, 4, -49, 32, 7, 6, -34, -5, 50, 14, 9, -35, -12, -1, -20, -50, 28, 23, 12, -39, -23, 7, -39, -20, -30, 48, -17, 25, -9, 8, -58, 38, -4, 26, -42, -21, 59, 27, 3, -21, -10, -35, 5, 0, 10, 28, -21, -1, -3, -5, 7, 24, 6, -43, 34, 20, 24, -29, 0, -42, -24, 23, 9, -27, 35, -8, 26, 44, -19, -44, 15, -21, 28, -14, -5, -26, 28, 30, 32, 18, -13, -23, -23, -10, 7, -36, 13, 37, -19, -18, -9, 21, 13, -5, 35, -19, 28, 12, 19, -4, 36, -32, -3, 32, -53, 27, 6, -25, 5, 23, 5, 14, 12, 21, 11, 41, -19, -28, -20, -14, -6, -12, -36, 60, 23, -5, -26, 25, 12, 5, -17, -10, -28, -17, 9, 22, -8, 4, 26, -34, 20, -7, 28, 30, 31, -26, -1, 6, -47, 6, 16, 32, 1, -24, 29, -4, 17, -3, 34, 31, 8, 17, -21, 27, 33, -35, 25, 26, -21, 9, 22, 9, -6, 15, 18, -8, 7, 11, 8, -33, 18, -44, 0, -3, 31, -21, 35, 24, -4, 15, 39, -15, 48, -13, 18, 33, -1, -9, -13, 34, -28, -31, -16, 23, 17, 20, 27, -46, -18, 30, 1, 17, -24, 18, -33, 15, 10, 29, 30, -45, 27, -17, 22, 6, 31, 55, 12, 40, -1, 29, 20, 27, 1, 2, -26, 16, 4, 8, 7, 19, 7, 8, -19, 17, -4, -31, 18, -61, 8, 7, 4, -36, 2, -35, 22, -14, -25, 28, 2, -14, -18, 5, 33, 17, -26, -27, -8, -5, 40, 7, 1, -7, -17, -5, 27, -41, 8, -17, -57, -41, 8, 56, 42, -16, -50, 26, 24, 18, -4, -12, 8, -20, -9, -34, -41, -28, -11, 17, 13, -2, -12, 41, 8, -20, 4, 11, 7, -49, -19, -35, 28, 38, 31, -9, -35, 2, -2, -42, -27, -42, 17, -7, 39, -27, 39, -14, -22, -9, -38, 13, 24, 21, 15, 6, 6, -43, -45, -9, -36, -13, 15, -31, -33, 46, -31, -10, 10, -31, -31, -1, 15, -5, -41, 41, -32, -11, -20, 11, 30, -23, -17, -20, 37, 18, 14, 17, -6, 43, -15, -46, 32, 22, -44, -9, -25, -9, -59, 47, -51, -15, -5, -24, 51, 27, -20, -3, 39, -7, -45, -53, 31, -37, -5, 35, -26, -22, 4, 18, -57, 16, 35, -39, 18, -24, -2, 18, 6, 21, 43, -42, 34, 9, -36, 12, -13, 2, 14, 22, 49, 23, 31, -30, -36, -2, 37, 7, 28, -24, 19, -25, 33, -3, -19, -4, 3, 28, 22, 9, -10, -13, -33, 4, -27, -23, 14, 27, -13, 13, -2, 8, -4, -41, -12, -26, 7, 1, -53, -11, -2, 13, 26, 34, 6, 38, -17, 10, -24, 16, 17, -9, 52, 9, 7, -36, -6, 13, -4, 32, -24, -22, -8, -6, -46, 16, 23, 13, 16, -58, 5, -8, -25, 15, -26, 40, 56, -10, -10, -16, -13, -23, -9, -65, -29, 26, -28, -38, 23, -36, 31, -16, -37, -29, -1, -6, -20, 9, 5, -31, -35, -11, 0, -6, 3, 20, -10, -53, 27, -10, -13, -20, 0, -23, -6, -3, 41, -48, 0, 36, 2, -7, 17, -46, -12, 3, -1, -27, -37, -18, -12, -8, -18, 9, 12, 15, -11, -53, -9, 33, -11, 12, 10, -37, -19, 26, 23, 23, 4, -19, 14, -18, 14, -36, -41, -16, -42, -18, 33, 23, -27, -28, 22, -22, 24, 9, -51, 16, 39, 3, -5, 19, 2, -29, 17, -17, -5, -9, -47, 1, 34, 1, -18, -29, 8, -26, -5, 32, -15, 39, 0, 13, 28, -10, -10, 14, 37, 25, -40, -2, -31, 0, -43, -15, 23, 4, -24, -12, 28, -3, 29, -10, 5, 14, 34, -8, 22, -24, 8, -31, 23, -14, -24, 27, -41, -5, 45, 47, 30, -7, -18, 10, -21, 31, -45, -16, -37, 8, 12, -29, 10, -7, -7, 5, 9, 27, -11, 42, 28, -16, 20, 0, -36, 15, -8, 5, 45, -16, 22, -14, 20, 11, -14, -27, 4, 30, -39, 4, -33, 42, 31, 37, 43, -35, 29, -35, -7, -6, -45, -57, -12, -32, -28, -59, 44, 1, 22, 34, 18, 15, -1, 3, -41, 33, -19, -1, 31, -19, 29, -20, 30, -56, -12, 18, 31, 14, 18, 13, 40, -21, 26, 11, 27, -25, -21, 10, -27, 3, -10, -50, 8, 45, 40, 31, 1, 9, -12, 10, 8, 4, -4, 21, -29, -24, -48, -25, -13, 25, 14, -42, -30, -33, 7, 21, -27, -38, -32, -36, -30, 28, -17, -41, 2, 29, 57, -8, -50, 21, -19, -34, -33, 3, 31, -4, -35, -15, 28, 12, 9, 45, 3, -11, -24, 2, -4, 39, 25, 36, -7, -33, -16, -8, -14, 57, 19, -10, -19, -39, 19, 25, -28, 16, -21, -33, -47, -15, 16, 27, 20, -35, -12, 10, 26, 5, 46, 16, -46, -21, 36, -9, -1, -36, -2, 7, -24, 13, -4, 10, 8, 27, 19, 12, -6, -36, 1, 22, -36, -13, 15, 20, -23, -45, -29, -10, -10, -2, -8, -10, 37, -6, -26, 21, -19, 22, 35, 8, 2, -49, 16, 27, -39, -27, -25, 31, 35, -20, -15, -5, -1, -30, -17, -17, -52, -30, 0, -12, 12, 44, 28, 43, 24, 12, 5, -34, -57, 51, -18, -15, 12, -58, 33, -21, -8, -28, -31, 19, 7, -42, 25, 6, -25, 19, 9, 8, -21, 40, -42, -45, 2, 12, -18, 14, -42, -35, -22, -15, 13, 12, -14, 15, 20, 22, 15, 55, -17, -21, -37, -1, -27, -3, 12, -3, 15, 18, -4, -7, 23, -18, 23, -14, 14, -41, -5, -32, -27, -50, -33, -28, -22, -16, -37, -26, -5, 14, 38, -34, 40, 40, 31, -17, 7, 19, -15, -34, -9, 0, -27, 38, 12, 8, 31, 15, 25, -6, 1, 36, 41, -11, 3, 29, 7, -15, 32, -34, 4, -35, -8, -22, -13, -30, 5, -18, 25, 5, -25, -22, -3, 33, -38, -7, -6, -39, -35, 26, -36, 4, -39, 18, 21, 26, 15, 25, -20, -35, -18, 24, -2, -18, -25, -43, 24, -21, 0, 14, 35, -14, -30, -30, -35, 19, 20, -60, 8, -4, 21, 35, -1, 8, -31, 35, -7, 15, -27, -15, -24, -27, -29, 30, -18, -4, 14, -7, -25, -20, 1, 4, -5, 13, -12, 32, -20, -26, -36, -3, 19, -2, -15, 2, -13, -37, -17, -4, -44, -33, 22, 20, -25, 3, -18, -24, -42, 20, -54, -30, 14, -30, -3, 3, -44, 0, -3, -25, -2, -5, 31, -19, -26, -5, -21, 36, 7, 41, 14, 20, 18, 26, 17, 28, 25, -18, 12, 3, 4, 4, -16, 30, 7, -41, 37, -35, 25, 45, -4, -44, 3, 19, 5, -76, 32, -24, -46, -5, 12, 9, 4, -3, 17, 14, -25, 6, -28, 20, -35, 2, 32, -39, -25, 5, 49, 33, 30, -25, 0, -15, -20, 7, 31, 15, -32, -20, -6, 17, -29, 27, 26, 21, 30, -16, -23, 60, -19, -6, 31, 22, 9, 14, 66, -11, 30, -38, 37, -7, 17, 23, 34, 24, 16, -1, -6, -15, 35, 19, 16, 21, -16, -15, -6, 11, 38, 28, 9, 19, -1, -31, 20, -29, -30, 30, -58, 22, 26, -18, -14, -61, 16, 15, 33, -12, 36, -19, -38, -20, 18, -3, 37, 25, 0, 8, 11, -17, 6, -19, 19, -1, 2, -9, 19, 24, -37, 5, 23, 26, 11, -15, -25, -14, -38, -12, 1, -8, -23, 46, -8, -1, -4, -13, 27, -13, -33, -19, 23, -48, -6, -23, -21, 12, -4, -16, -26, -23, -10, -32, -52, 9, -6, -28, -60, 27, 0, -45, -31, -24, 0, 37, 2, -21, -38, -34, -40, 32, 11, -12, -4, 7, -38, 7, 15, 5, 8, 37, 29, 13, 8, -3, -22, -7, 5, -46, -9, 1, -9, 36, -56, 26, -45, 33, -46, -30, -5, -5, -47, 46, 12, -29, -34, 13, -3, 6, 2, -14, -1, -15, 16, 15, 51, 4, 19, -12, -42, -14, -47, -41, 15, 11, -25, 14, 38, -2, 35, 34, 1, -12, 9, -3, -1, -7, -19, -25, -37, -6, -38, -16, -18, -19, -10, -18, -19, -14, 4, -35, -50, 13, -8, -12, 42, 59, -62, -12, 35, 5, -6, -32, -33, -9, -31, 21, -27, 24, 3, 5, -33, 9, -49, 10, -37, -27, 24, 10, -5, 16, -38, -25, -2, 0, 10, 8, 27, -52, 9, -44, 51, -49, 3, 0, -13, 8, 17, -15, -31, 17, 43, -14, 28, 26, 1, -17, -67, 41, -27, -18, -69, -21, -30, -21, -17, -31, 41, 8, 12, -16, 42, 28, 5, -38, -25, -10, 10, 38, -45, -13, 39, -13, 14, -6, 36, 27, 22, 3, -3, 37, 23, -4, -4, 13, -12, -1, 20, -12, 8, 12, -7, 15, 7, -4, -49, 46, -38, 6, -16, 2, 3, -37, -53, -8, -28, -18, 31, -6, -9, 16, -27, -1, 40, 5, -32, -63, -22, -5, -38, 31, 17, 20, -28, 15, 43, -34, -3, 29, 42, -25, 38, -41, -34, -15, 24, 15, -17, 9, 28, 16, -21, 4, -43, -46, 24, -24, 30, -59, 15, -23, -28, -24, -16, 22, 30, -22, 12, 4, 10, 25, -28, -4, 0, -20, 2, -30, 20, 27, -17, 5, -25, 25, 17, 61, -52, 0, -15, 4, 19, 0, 20, -17, 53, 2, -6, -12, -10, -41, -27, 17, 38, 12, 18, 32, -6, 17, 28, 8, 14, -32, -31, 45, -53, -69, 28, -7, 21, -1, 45, -31, 22, 16, 5, 42, 12, -34, 38, -9, -6, -2, -19, -18, 3, -10, -8, -25, 34, 20, -48, 25, -3, 4, -24, 21, 2, -24, 29, -15, -21, -4, -39, -4, -17, -9, 29, -18, -2, -7, -8, -47, -31, -9, -44, -8, 42, -3, 41, -21, -9, -63, 55, -13, 29, -13, 11, -26, -52, -13, 18, 21, 17, 0, 39, 12, -14, -43, -30, -39, -9, 14, -27, -13, -1, -37, -1, -35, 25, -21, -52, 27, 32, 14, 0, 1, 6, 36, -15, -39, -1, 11, 22, 9, -11, -35, -45, -7, 13, -29, -34, 1, -14, 1, 17, 38, -23, -32, 23, 12, -58, -75, -39, -15, 19, -54, 4, -32, -17, 29, 2, 7, 21, 1, -42, -16, -5, -3, 30, -18, 37, 29, -21, 2, 44, -10, -22, 23, -22, -23, 48, -5, -11, 41, -30, 2, 37, -27, -78, -8, -15, 14, -40, -27, 25, 39, -27, 10, -6, 8, 29, -28, 21, -12, -21, 6, -17, -13, -25, 7, -11, 18, -1, -14, 41, 21, 11, -35, -25, 34, 22, 16, -31, -45, 13, 7, 35, 9, -52, -54, -11, 1, 7, 4, -23, 1, 17, 10, -15, 14, -40, 9, 20, -30, -1, -14, -33, -48, 2, -6, 3, -42, -11, -18, 21, 18, 48, -71, -19, 17, 11, 3, -31, -20, 27, 7, -13, 18, -8, -22, 12, 6, 22, 19, -6, -47, 4, -25, -25, 12, -1, 0, 22, 24, -38, -14, 6, 30, -3, -14, -56, 21, -24, -9, -68, 13, -26, 5, 35, 16, 14, 21, 14, 0, 20, -24, 8, 30, -25, -2, 7, -18, 11, 14, -33, 24, 19, -18, -47, 15, -13, -6, -47, 28, -24, -13, 11, 14, 11, -8, 13, -1, -33, -22, 12, -55, 7, -34, -11, 37, -50, -8, -11, 37, -13, 10, 26, 12, 3, 18, -4, 56, -2, 50, 47, -16, -10, 24, 23, 36, 7, -23, 41, 2, 2, 35, -11, -17, -10, -16, -31, 1, -47, -32, 24, -11, 13, 28, 10, 23, 42, 30, -32, 45, 30, -18, -46, 24, 25, -18, -33, -45, -5, -12, -27, 54, 62, -8, -20, 9, -27, 29, 2, 1, 3, -3, -23, -1, 35, 20, 0, -15, 41, 30, 33, -17, -15, 18, 35, 21, -38, -39, -5, -37, -3, -28, 16, 19, -4, 4, 30, -36, 33, 11, -19, -34, -34, 32, 34, 4, -42, -16, -13, 18, 24, -25, 30, 27, -25, -29, -39, 29, -24, -14, -3, -44, -7, 13, -52, 17, -22, 12, 0, 10, -36, -20, 22, 40, -15, 10, 10, -32, 30, 29, -12, -18, 21, 10, -10, -7, 1, 10, 14, 22, 27, 24, -8, 9, 16, -29, -93, 48, -7, 36, -4, -49, -23, 31, -1, -13, -1, 36, -9, -17, 36, -27, -21, -21, 42, 20, -6, 53, 2, 28, 41, -8, -23, -7, -13, 11, 31, 3, -7, 4, -22, 34, -11, 35, 23, -13, -22, 12, -18, -5, 37, 1, -23, -17, 0, -35, -29, 53, -15, 18, 7, -16, -18, 23, 17, 37, -1, -10, 30, -28, 38, -35, 12, -27, -47, 31, -19, 30, -29, -30, -38, 20, 25, -21, -23, -24, 29, 34, 4, -5, 31, -28, -17, -33, -16, -31, -17, -25, 19, 10, -8, 27, 13, 22, 10, 35, -9, -17, 26, -18, 24, -33, -17, 31, 9, 10, -29, 34, 2, 2, 22, 12, 9, 14, -5, -29, -11, -13, 1, 3, -17, 28, 31, 23, -7, -26, 27, 31, 38, -14, -8, -10, -17, 59, 11, -6, -29, 8, 13, -1, 12, 4, 13, 26, -2, -33, 14, -12, 15, 60, -44, -16, 12, 35, -40, -12, 23, 8, 15, 13, -14, -9, -15, -15, -18, 21, -37, 7, 45, 27, -29, 11, 44, -8, -6, 3, -4, -9, 2, -52, -28, -22, 34, -8, 15, 32, -24, -26, 5, -17, 24, -18, 28, 15, -21, 31, 21, 7, -15, 23, 16, -22, 28, -14, 43, -23, -1, -8, -22, -29, -8, 36, 4, 24, -2, -10, 34, 5, -36, -11, -16, -10, 32, -17, -9, -18, 29, -35, 26, 3, 8, -1, 7, 8, -14, 36, 1, -7, -33, -31, -26, -2, 33, -17, -1, -32, -38, 38, -39, 21, -14, -9, -7, 22, -31, 40, 33, -34, 4, 4, -18, -16, 27, -48, 13, -26, 1, -33, 48, -35, 7, 15, -57, -2, -24, 27, -31, -16, 38, 46, -7, 35, -55, 39, 9, 8, -11, 8, 39, -19, -45, 11, 10, 39, -49, 23, -23, -48, -21, -25, 45, 17, 26, 23, 42, 18, 17, 31, -38, 11, -8, 9, 8, 16, -31, 5, -30, -16, 26, -65, -40, 22, 4, -26, -39, -15, 5, 14, -4, 35, 17, 12, 39, 17, -14, 22, -6, -21, 54, -2, 14, 10, 17, -40, 32, -35, -86, 9, 38, 41, 35, -8, -10, -33, 29, 2, -4, -16, 14, -28, -5, 12, 3, -44, 12, -50, -21, -2, -28, -11, 12, -26, 4, 10, 3, 31, -37, -52, 6, 39, -6, 53, 3, -18, 2, -19, -24, 34, -45, 10, -11, 22, 25, 8, 13, -23, -21, -28, -53, -17, -36, 34, -28, 35, 5, 34, 9, 7, -15, 2, -20, 1, 8, 3, -1, 28, -9, -28, 3, 11, -34, 10, -21, -40, 2, 6, -14, 26, 27, -54, -32, -12, 61, 11, -15, 17, -31, -8, -2, -6, 1, 46, 7, 27, 12, 7, -16, 13, 11, -33, 8, -5, 32, -49, -16, -15, 6, -23, 17, -10, 21, 9, -19, -32, 18, 38, -9, -6, -14, 17, 8, -13, 22, 5, -11, 3, -9, 4, -32, 34, -21, 23, -21, 22, -38, -9, -2, 5, 4, 20, 21, -19, 33, -52, -6, 6, 23, 19, -19, 40, 33, -19, -11, -56, 32, 18, -1, 35, 23, 15, 25, -10, -19, -23, 19, 3, 12, 36, -8, 35, -6, 47, -15, -18, -29, -4, 48, 1, -3, 14, 28, -24, -10, -24, -31, 13, -10, -5, 6, -23, 48, 35, -21, 23, 25, -6, -15, -52, 35, -39, -27, 27, 55, -22, 43, 30, -4, 15, 5, -18, -22, -30, -3, -9, -46, 19, -12, -42, 10, -46, 58, 7, -56, 12, 2, 31, -16, -17, 10, -21, -25, 27, -22, -21, -30, -17, -12, 36, -2, -12, -10, 11, -25, 28, -23, -27, -40, -4, 35, -11, 26, 2, -13, -3, 9, 0, -3, 15, -27, 19, 32, -38, 11, 10, -29, 29, 23, 17, -24, -27, -7, -13, -19, -17, -22, -17, -16, -23, 27, -14, -6, -3, -28, 26, -37, -11, 20, 6, -37, 18, -26, 25, 14, 17, 9, 20, -9, 30, -32, -6, 28, -38, -38, 17, -4, -8, -16, -45, -9, -21, 27, 6, -22, -34, -37, -19, 16, -13, -30, 21, -5, 3, 9, 5, -20, -38, 11, -2, 17, 7, -30, -15, -23, 37, -5, -17, -17, -1, 37, 2, -38, 4, -11, -31, 19, -26, -39, -17, -40, 6, 13, -3, 30, -7, 32, 13, -44, -29, -22, -4, 0, -7, 4, -9, 6, 7, -49, 14, 26, 10, -6, 42, -9, -16, -30, -14, -15, -35, 5, 12, -32, -3, -9, -20, -26, -41, 30, 5, 53, 41, 11, -29, 62, -37, -26, -21, 11, 5, -15, -3, -24, -23, 27, -36, 0, 27, 25, 20, 14, 3, -27, -43, 11, -5, 5, -17, -12, 54, 19, -46, -45, -45, -10, -21, -23, 8, 28, 29, 25, 4, 1, -3, -10, -11, -12, 7, 36, 6, -36, -17, 31, 63, -20, -13, -6, 11, 27, 8, 13, -1, -58, -15, -11, -6, 7, 17, -20, -13, 34, -14, 0, -52, 13, -7, -11, -40, -32, 33, 22, -3, 28, -19, -12, -6, -23, 26, -31, 24, -20, 39, 22, 21, -7, 32, 22, -58, 11, -29, 24, 29, -38, 32, -13, 5, -12, 5, 16, -10, 14, -17, -30, -43, 0, -28, -27, 30, 5, 5, 24, 13, -40, 5, 61, -12, 2, -19, 25, 5, -12, 20, 9, -34, 28, -44, 52, -44, 12, -1, 21, -21, -12, -57, -21, 29, -38, 56, 18, 1, -42, -9, 8, -25, -44, -27, -40, -19, -8, -16, -30, 28, 28, -13, 29, 33, -16, -1, -6, 28, -41, -24, 26, -20, 29, 14, -8, -34, 22, -31, -4, 16, -31, 25, 3, -27, 36, -36, 38, -48, 7, -42, 26, -22, -40, 25, 6, -25, 10, 17, 8, -21, 4, 6, -26, 38, -2, -22, 38, -25, -36, 29, 37, -11, 6, -5, -8, 2, -33, 6, 49, 8, -8, -43, -14, 27, 17, 26, -28, -17, -27, 13, 0, 2, -21, 4, -32, 10, -18, 17, -47, 18, 6, 25, 25, 16, 12, -2, -31, -9, -3, -52, -13, -58, -26, -36, -17, -14, -35, -9, -21, 0, -23, -3, 1, 16, -12, 17, -6, 12, 24, 8, -4, -23, 19, -13, -12, -18, -3, 37, 32, -8, 2, 26, 6, -8, 5, 52, -59, -23, 27, -10, -6, 41, -18, 31, -48, -43, -6, 24, -14, 1, 43, -33, -8, -10, -58, 21, -8, -17, 21, 38, 32, -45, 36, 38, -8, 21, -11, 2, 5, -8, 30, -10, -14, 9, 21, 33, 2, -16, -17, 44, 38, -28, -14, 6, 9, -31, 13, 27, 5, 31, -3, 39, 1, -33, -48, -37, -33, -53, 37, 38, -12, -4, -39, 35, -34, -26, -13, -33, 1, -30, 10, -19, 2, 14, -3, -35, 22, -11, -44, -59, -12, -56, 1, 16, 1, 11, -30, 28, -4, -27, -45, 33, -28, 25, -26, 6, -8, 13, -43, 10, -7, 14, 47, -27, 11, -32, -17, -2, -18, -17, -14, -10, 25, -11, 24, 7, -14, 8, 33, -36, -37, -12, 25, -37, -2, -21, 12, 18, 10, -22, 1, -1, -67, -21, -12, -47, 15, -42, 13, 0, 41, 21, -16, 29, 11, -4, -17, 2, -32, -2, -7, -35, 16, -9, 20, -6, 14, 8, 34, -31, -59, -1, -26, 13, 11, 24, 13, -18, 5, -5, -38, 15, -12, 58, 9, -23, 17, 26, -6, -5, -32, -12, 43, -19, -22, 28, -36, 40, -16, -39, -69, 26, -36, 32, -1, -14, 26, -14, -11, 21, 30, 5, 17, -59, 18, -47, -3, -13, -27, 11, 14, -20, -22, -14, -35, -18, 8, -19, -6, 8, -15, 12, 0, 35, 31, 8, 5, -14, 32, -19, 17, -18, 1, 12, 37, 13, 13, -12, 27, 1, 16, -8, -11, -20, -27, 13, -12, 2, 65, 7, 9, 20, 32, -15, 45, -21, -21, 1, -37, 32, 4, -29, 32, -19, -36, -44, -39, -37, 37, -43, 24, 24, -28, -10, -36, -2, -28, -37, -26, -35, -24, -38, 1, -2, 13, -10, 17, -26, -9, -1, 38, -11, 34, -15, 33, 4, 35, -51, 13, -9, 1, -34, 28, 16, -10, -2, 16, -54, -47, 0, 13, 17, -5, 42, -1, 18, -22, 28, 2, 0, -2, -20, 32, 2, -15, -38, 8, 3, 3, -27, 8, -35, -12, 38, 38, 41, 37, 12, 14, -21, -8, 50, -31, 39, 10, 45, -10, 24, -15, 16, 16, 6, 31, -27, -20, -6, 5, 18, -21, 18, 29, 20, 19, -34, 28, -30, -15, 0, -20, 10, -3, -25, 13, -11, 20, 13, -34, -8, 25, -5, -10, 19, 2, -21, 42, 7, -41, -27, 23, 26, 21, 0, -23, -4, 28, 6, 30, 34, -10, 18, -61, 42, -10, 9, -24, -16, -12, 21, -45, 39, -4, -6, 16, 15, 31, -23, -31, 19, 0, 25, -12, -19, 21, -14, -21, 27, -39, -18, -34, -5, 5, 34, 21, -29, -30, -24, -30, 3, -36, 14, 5, 57, 15, -9, -40, 5, -37, -34, -5, 2, 30, -17, 39, -10, 25, -33, 3, 31, 17, -10, -11, -38, 16, -68, -33, -21, -46, 6, -30, 12, 8, -47, 51, -11, -8, 37, -24, 11, -43, -37, 8, 29, -46, -9, 21, 17, 26, 4, -57, 28, -34, 43, -34, -31, -12, 34, -12, 23, -28, -30, 47, -33, -30, -58, -30, -38, 36, -21, -38, -21, -6, 19, 36, -17, -20, -9, 4, 44, 7, 16, -33, -58, 26, 6, 13, -21, 25, 11, 24, 57, 30, 26, -3, 5, 15, 2, 0, 6, 18, 19, 10, -3, 0, -12, 1, -25, -21, -11, 53, -3, -11, -4, 30, -15, -59, 5, -23, 47, 29, 20, -30, -17, -12, 6, -7, -26, -5, -26, -28, 0, 30, -20, 5, 0, 8, -42, 1, -41, -14, -35, -16, 12, -30, -13, 13, 17, 0, -32, -18, -24, -12, 10, -12, 24, 18, -25, 16, -25, -14, -31, 53, -10, -6, -3, 19, -47, 18, -22, 49, 29, -2, -13, 15, 16, 21, 2, 6, -18, -7, -10, -13, -23, -21, -13, -12, -3, -43, -4, -28, -24, 28, -4, 18, 6, 24, -11, 33, 15, 19, 41, 31, -18, 24, -17, -3, 27, 40, -32, -39, 7, 39, 19, 31, 24, 23, -11, -12, 6, -41, -7, 14, -18, -67, 40, -10, -15, 37, 21, -22, -6, 17, -43, -51, -17, 14, -20, -4, 10, -8, -48, 25, 19, 6, -29, -39, -25, -2, 21, -6, -15, -4, -30, -12, 27, -21, -21, -1, -27, -15, 20, -10, 46, 24, 7, -11, 22, 5, 6, 37, -12, 33, -2, -46, 9, -23, -2, -13, -10, -40, 45, 38, -38, -6, -27, 8, 27, -8, 33, -10, -11, -36, 1, 35, 11, -25, 28, 23, 44, -20, 22, -39, -1, 7, -29, 46, 0, 1, -33, -2, 36, -9, 20, -4, 37, -36, -15, -19, -41, -18, -21, -41, 31, 45, -25, 10, 28, -24, 4, -16, -44, 14, 8, -18, 2, -2, 16, -48, -6, -1, 28, 15, -38, 29, 13, -32, -19, 3, -3, -61, -29, -11, 9, -21, 3, -20, -18, 7, 23, -39, 1, -8, 19, 0, -6, -24, -3, 13, -51, 20, 18, 35, 10, -1, 38, 1, 38, 8, -12, -27, 0, -4, 8, -1, 20, 30, 33, 7, 2, 18, 27, 15, 8, 39, 26, -3, 21, -26, -30, -85, -2, 8, 22, -5, -26, 16, -28, -3, 7, -12, 4, -2, -5, 9, 5, 2, -34, -19, -2, -38, 48, -19, -36, 9, 18, 2, -23, 22, 0, 20, 4, -43, -27, -28, -9, 0, 24, -8, -46, 0, 18, 36, 25, 23, -10, 1, 30, 9, -12, -8, -34, 40, -12, 17, -52, 30, 7, 22, -17, -22, -42, 8, 0, -41, 31, 0, -4, 22, 8, 8, 39, -27, -7, -2, -40, 10, -3, 25, -26, -22, -34, -12, 39, -17, 54, 52, -32, 1, -24, 13, -33, -7, -39, 48, -20, -22, 36, -16, 18, -16, -32, -16, -26, -40, -10, 0, -9, 7, -35, -42, 17, -17, 25, 27, 37, 20, -14, -6, 20, -3, -23, 18, -17, 42, -9, 32, -10, -7, -10, -51, -4, 9, -20, 27, 13, -45, 15, 29, 31, -43, -23, -30, 1, -1, -34, 0, -9, 4, -30, -10, 10, 25, 33, 13, 18, 52, 1, -11, -1, -4, 30, 10, -11, 13, -30, 35, 30, -8, 49, 5, 17, 13, -18, 6, 10, -35, -10, -22, 5, -18, -20, 51, 1, 25, -10, -22, 60, -1, -20, -4, -21, 6, -35, 23, 53, -7, -27, 26, -23, 8, -35, 6, 12, -12, 6, 15, 0, 15, -23, 16, 25, -28, 27, 4, -60, -37, 29, 46, -28, 17, -5, 1, 2, 13, 39, 22, -33, 46, -37, -6, 48, 8, 25, -1, -17, 12, -14, 25, 21, -21, -22, -16, -6, 42, 1, -15, -26, 15, -18, -22, -44, -25, 39, 12, 15, -16, -12, -11, -18, -15, -30, -57, -17, -13, -2, -23, -28, -26, 26, -28, -1, -20, -98, -21, -15, -4, 9, -11, -6, -24, -3, -1, 19, 7, 32, 13, 11, -32, 15, 24, -15, -5, -42, -5, 30, 9, -23, 52, -49, -11, -25, 20, 33, -18, 16, -23, -19, -30, 14, -15, -23, -2, 27, -54, -21, 6, 15, 18, 0, 21, 41, -23, 35, -42, 9, 10, -9, 19, 8, -31, -6, 6, -9, -8, -14, -42, 20, 36, 24, 17, 6, -35, 4, -13, 12, 31, -12, 14, -27, 46, 3, 20, -9, -16, -35, 23, -1, -15, 30, -16, 23, -3, -42, -48, -32, 24, 4, -57, -10, -33, 4, 17, -53, -25, 25, -21, -35, 65, 12, 28, 3, 4, 28, 37, -44, 38, -47, 46, -11, 31, 13, 27, 28, -19, -5, -27, -22, -9, -3, 21, 22, 31, -22, 1, 14, 10, 32, 9, -35, 38, -45, 0, -4, 26, 25, -35, 7, -49, -25, -16, -5, -11, 2, -36, -19, 2, -12, 8, -4, -21, 16, -43, -5, -2, -34, 4, 91, 27, 10, -26, -41, -29, 18, -37, 5, 27, 47, 34, 18, -38, 17, -40, -35, -13, -6, 47, -10, 6, 15, -27, -35, 31, -13, 11, -1, 1, -5, -23, 18, -12, -26, 29, 43, -19, 23, -4, 39, 22, -30, 26, -11, -37, -3, -7, 15, -26, 3, 25, 24, -16, -2, 38, -27, -25, 29, -6, -5, 19, -3, -41, 4, -36, 22, 31, -28, 6, -2, 36, 32, 36, 43, 12, -4, -44, 11, -29, -17, -11, -24, 21, 14, -1, -5, -48, 2, 17, 25, 17, 24, 15, 41, 7, -34, 29, -11, 29, -28, 13, -24, 16, 47, -18, 14, 18, -4, 12, -13, 2, -46, -14, 34, 11, -27, -2, -42, -18, -15, 3, -20, -33, -7, 2, -9, 22, 5, 32, 15, -6, -32, -42, 33, 19, -16, 23, -25, 30, 0, 17, -23, -2, 29, -19, 20, 24, -6, -62, -6, -17, 11, -10, 36, -40, 20, -4, 16, -10, 27, -31, -12, 45, -40, 39, 2, -15, -65, -31, -13, -21, -4, -6, 24, 27, 38, -49, 19, -31, 8, -33, 38, 15, -31, -22, -16, 25, 27, 11, -9, -8, 9, 18, 36, 1, 24, -5, -13, 5, 20, -4, -32, 33, -17, 3, -4, 20, 13, 19, 21, 35, 0, -21, -12, -39, 15, -49, 12, 2, -49, 18, 5, -17, -12, -44, -61, -27, 18, -16, -9, 22, 3, -4, 24, -24, 20, 17, -3, 25, 4, -28, -34, 22, 11, -26, -26, -8, -1, -35, 28, 4, 17, 3, -16, -10, 37, -10, -2, 7, -17, 8, -29, 20, -15, 16, 32, 18, -47, 25, -30, 25, -19, -22, 50, -9, -37, -28, 9, -21, -3, 16, 13, -44, -22, 34, -28, -29, -15, 23, 14, 10, -19, -26, 44, 14, -5, -41, -12, -16, -5, -28, -5, -19, 5, -1, 41, -22, -2, 43, 14, -7, -3, 5, -24, -3, 62, -40, -3, 14, 15, -32, -21, 10, -11, -20, 13, -29, -66, -28, 24, -45, 46, 12, -7, -13, -11, 13, 0, -24, -41, -5, 26, 12, 6, 8, -36, -8, 39, 36, 0, 43, 40, -35, 34, -16, -13, 2, -35, -27, -18, 17, 43, 31, -10, -24, 50, 28, 49, -26, -25, -11, 29, 25, -23, 20, -35, -36, -6, -16, -8, 23, -12, -35, 32, -20, 3, -21, 12, 40, 8, -34, -10, -2, 37, 5, 31, -2, -12, -32, -17, 16, -3, -12, 44, 16, 20, 11, -36, -11, 27, -35, 3, -22, 18, 26, 28, 15, 51, -62, -42, -50, 36, 11, -33, 12, -24, -66, -16, 47, -31, -35, -8, 11, -53, -9, -2, -4, -24, -24, -34, 18, 21, -7, -16, -36, -6, 33, 10, 2, 24, -2, -20, -3, 1, 6, -3, 22, 29, -41, -6, -1, -4, -10, 3, -20, 39, -32, 15, -52, 33, 26, 43, -3, 17, -27, 26, -37, -13, 35, -4, -2, -20, -10, 13, -36, 26, 10, -17, -74, 3, -9, 21, 17, -22, 24, 7, 23, 28, 5, -50, 3, -31, 20, 29, -6, -37, -18, -15, 15, 21, 0, -14, 11, -8, -21, 28, -44, 17, -26, -22, 21, -7, 49, 15, -36, -18, 0, -6, 44, -5, 37, 36, 30, 23, 26, -21, 7, 40, 20, 17, -19, -38, 51, -20, -1, 19, 14, -20, -22, 35, 14, -20, -81, -2, -30, -19, -15, 16, -5, -1, 26, -4, 38, 8, -10, -21, 11, -46, 20, 7, -44, -10, -3, -12, -25, -6, -14, -29, -28, 30, -2, -42, -45, 7, -34, 3, 17, -31, -9, -5, 4, 19, 29, 44, 3, 15, -61, -46, -8, 3, 34, -16, -23, 18, -2, 5, -19, 0, 5, 13, -62, -43, -37, 15, -7, 31, 22, -27, 30, 43, 22, -15, 14, 21, -7, 28, 17, 24, 47, -7, 6, 16, 40, -6, -8, -8, 7, -20, -13, 4, 38, 26, 36, -36, 8, -24, -5, 7, 4, 2, -33, 11, -5, -36, 25, -56, 25, -12, -37, -1, -6, -10, -12, 8, -44, 3, -60, 44, -3, 13, 38, -35, -16, 28, -20, -45, -15, 6, 23, -51, -18, 44, -31, -11, -13, -28, -13, 40, 10, -23, -6, -31, 2, 40, 27, 29, 19, 7, -12, -20, -42, -30, 44, -5, -30, -10, 12, 18, -25, -18, -1, -42, 14, -9, -39, 15, 0, 15, -20, -18, 41, -13, 7, 9, -1, 4, 3, -22, -10, -18, -41, -30, -52, -7, 14, 26, -42, 21, 23, -9, -10, -52, 34, -13, 42, -12, -34, 12, 16, 0, 24, 46, 5, 30, 0, 0, 47, -41, 26, -12, 7, -4, 8, 25, -33, -15, -22, 12, 33, 17, -26, -45, 7, -38, -15, -19, 20, 5, 5, 4, -9, -7, 39, -19, 33, 15, -31, 2, -15, -20, -48, -42, -8, 19, 12, -18, -20, 17, -21, 2, -8, 6, 36, 4, -12, 21, -30, -6, 24, -18, 2, -14, 20, 9, -40, 16, -13, 1, -35, -18, -6, 11, 19, 21, 17, 13, -21, -17, -5, 41, -49, -32, 32, 14, -26, 29, 7, 9, -18, -5, 8, 27, -23, 16, 34, -6, 33, -5, -11, 13, 14, 9, 33, 0, -23, -8, -3, -25, 21, -34, 26, -19, 13, -40, 7, -33, -8, 24, 64, -3, -13, -27, 23, 21, 14, 21, -27, 33, -19, -15, -26, -7, -19, 0, -21, -37, -3, -50, -6, 21, 38, -17, 0, 0, 27, 8, 49, -52, -16, -10, 12, 0, -27, 1, -7, -15, 26, -9, 7, -11, -24, 41, 15, -40, -13, 8, -7, -42, -12, -8, 4, 0, 5, 37, -22, -59, 16, 7, -40, 8, 2, -4, 37, 28, -14, -64, 10, 55, 53, -34, -15, -6, 7, -21, -46, 16, 11, 16, 2, 10, 24, -46, 16, 7, -14, -52, -22, 35, -36, -17, -2, 14, -18, -4, 37, 1, 40, -12, -19, 10, 17, -37, 9, 16, 11, -6, 52, -2, 20, -2, 33, 15, 47, 41, 52, 31, -22, -28, 19, -39, 19, 9, -13, -10, -7, -7, -36, -37, -41, 16, -12, -13, -43, 23, 27, 26, 25, 46, 17, 41, -7, 3, -21, -12, 9, 13, 14, -21, -9, 5, 2, -8, -23, -21, -27, -39, 18, -22, 31, -38, 8, -17, 2, 25, 4, -13, -43, 1, 14, 36, -33, 22, -50, 17, 9, 5, -24, -30, -17, -23, -29, -43, 17, 50, -21, -20, 44, 7, -11, 24, -41, -9, 55, 8, -34, -21, -17, -22, -20, 37, -47, -26, 13, 32, 23, -45, -5, -24, -45, -13, -13, 52, 17, 44, -40, -30, 7, 7, -10, 3, -19, -18, -6, 13, 49, -13, -30, -15, -15, 13, -28, -52, -11, -26, -6, -1, -5, -28, 8, -4, -19, -5, -14, -1, -41, -13, 39, -15, -17, -13, 22, 14, -21, -35, -14, -17, 16, 33, -13, 11, 19, 25, -21, 29, 5, -7, 0, -11, -51, -16, 9, -15, 80, 30, 14, 41, -18, 55, 4, -7, 27, 27, -1, -2, -9, 1, 43, -55, -23, 18, -52, 58, 34, 38, -9, -43, 17, -27, -25, 0, -24, 62, 46, -51, 12, -33, -6, 4, 19, -27, 24, 9, 11, -15, 47, 26, -8, -16, -30, 13, -60, 20, -11, 33, 6, 26, -3, -4, -9, -21, 6, -6, 5, 2, 31, 1, 24, 4, -2, -19, -37, 40, 23, 14, 0, 3, 34, 40, -3, 4, 23, -10, -30, 34, -29, -42, -20, -37, 6, 2, -7, -32, -25, 42, 20, -51, -22, 9, -18, -22, -16, -39, 47, 11, -6, 45, 32, 17, -6, 17, 5, -31, 26, -9, 69, -17, -21, 3, -19, 5, 67, 9, -24, 53, 9, 29, -13, -30, -1, -21, -41, 22, -4, 19, -1, -37, -15, 15, 14, -26, 9, -59, 40, -55, -32, 39, 14, -16, 3, -17, 9, 19, -28, 20, 50, -57, 12, -53, -6, 21, 20, 10, -8, -22, -23, 0, -44, -41, 13, 17, -29, 34, -24, -6, 38, -19, -10, -43, 7, -18, -10, -11, -34, 40, 21, 17, -49, 30, -8, -21, -46, 45, 18, -20, 36, -9, 38, 20, -50, 23, 21, -8, -14, 14, -1, 47, 13, 26, -1, 20, 6, -12, -42, -8, 24, 13, 29, -10, 12, -22, -36, -5, -35, -47, 7, -14, -23, 10, -30, 29, 18, -17, -27, -36, -52, -12, -5, -26, -30, 19, -32, 11, 15, -34, -30, 10, -9, 26, -4, -7, -24, -9, -9, 32, 16, 24, 9, 43, -33, -21, 9, -17, -39, 1, 9, -2, 1, 5, -24, 10, 42, 26, 31, 25, 21, 46, -6, -3, 27, 20, 24, 1, 22, -1, -26, 45, 12, 15, -29, 4, 33, -6, -9, 18, -62, -16, 8, -28, 7, -53, -32, -42, -45, 7, 19, 10, 29, -30, -31, -38, 38, -7, -55, -32, 2, 2, -33, -3, -8, 28, 28, 54, -40, -19, -24, 31, 42, 25, 28, -27, 13, -27, -4, -16, 10, -1, -5, 15, -3, -12, 23, 5, 42, 3, -28, 22, -25, 22, 14, -26, 2, -64, 16, -12, 61, 12, -20, -22, 5, 9, 47, 15, -19, -2, -10, -48, 21, -36, 5, -16, -50, 17, -49, -19, 4, -27, 28, 39, 16, 9, -24, 30, -47, 35, 33, -4, -17, -13, 16, 14, 1, 13, -40, 0, -18, -34, 55, -49, 5, -30, 19, 28, 22, -2, -24, 38, 24, -39, -21, -8, -31, -51, 45, -14, -17, -43, -48, 20, -18, 10, -45, 5, -19, 22, -33, 30, -48, 39, 4, -6, -13, -15, -1, -10, -8, -53, 3, 0, -28, 23, -35, -12, 0, 6, 30, 39, -14, -5, -64, 8, -6, 2, 19, -9, -10, 15, -30, -32, 17, 27, 4, -40, 3, 42, 6, 0, 2, 25, -1, 23, -35, -49, 19, 17, 10, -15, -36, 19, 13, -26, 13, -16, -45, -21, 12, 18, 31, -20, -17, -6, -45, 60, 19, 45, 3, 25, 35, -13, 3, 27, 35, 18, -16, 2, -25, 1, -55, -27, 17, -26, -32, 1, -19, 7, -3, 28, 39, 16, -3, -14, 2, -9, 15, -7, 0, -26, 19, -15, 12, -10, -1, 20, -22, 26, 21, -30, 47, 5, -45, 24, -27, -20, 11, -10, -23, -7, 45, -25, -12, 0, 16, 22, -2, 25, -37, -25, 29, 26, -11, -24, -17, -6, -13, 28, 15, 32, 6, -26, 57, 40, -30, 21, 1, -26, 1, -11, 29, -31, 15, 33, -21, -15, 38, -11, -27, 22, -14, 2, 9, -35, 41, -5, 44, -37, -16, -21, 15, 13, -23, -32, 38, 17, -4, 9, 14, -19, -15, 5, -15, 1, 31, 18, 39, -21, -32, -9, 2, -51, 29, 34, -53, -68, 16, 23, 22, 34, 19, 40, 16, -13, 1, -16, -1, 3, -28, -7, 16, -12, -61, -20, -1, -11, 0, 8, 14, 6, 12, 30, 13, -18, -42, -24, -18, 8, -4, -15, -21, 26, -20, -23, -5, -16, 18, -23, -28, -44, -2, -38, 31, -21, 12, -30, -37, 32, -20, -2, -16, 17, 4, 30, 15, -28, -21, 11, 17, 26, -23, 21, 6, 38, -19, -3, 33, -31, 3, -18, -19, -13, 16, -28, -41, 48, 29, 12, -27, -1, -24, 38, 19, 6, -31, 24, 17, 47, 4, -21, -8, 50, 41, 25, 17, 19, -43, -3, 26, -32, -52, 27, 7, 10, -35, 10, -54, 29, -42, 29, -2, -5, -31, -22, 10, -2, 2, -23, 43, -42, 21, -10, 60, -13, 8, 17, 29, -25, 37, 4, 35, -17, -21, -16, -5, -24, 21, 7, -11, -14, 10, -44, -58, -4, -13, 7, 7, 34, -4, 14, 7, 28, -18, 7, 16, -7, 19, 21, 25, 3, -44, -16, 14, -1, 54, 11, 6, 1, -24, 30, 12, 3, -1, 3, -22, -3, 30, -48, -13, 10, -7, -25, 2, -32, -32, -4, 2, -58, -34, -18, 17, -11, 21, -8, -19, 1, 2, -35, -39, -20, 60, 22, -8, 1, -12, 14, 8, -2, -18, 35, -29, -22, 6, -14, 31, -31, -42, 53, -17, -10, 36, -32, -50, -9, 15, -18, 35, -12, -23, -39, 47, 0, 1, 22, 29, -29, -44, 20, -23, -32, 33, 37, -2, -18, 22, 33, 7, 12, -17, 24, 20, 19, 21, 22, 30, 35, 21, -16, -13, -22, -32, -8, -7, -6, -17, -6, -43, 15, 21, 10, -25, -28, 41, -77, 5, 16, 11, 24, 40, -3, 14, 7, -72, 20, 30, -5, -56, 16, -50, 6, 10, -55, -4, -11, 17, 9, -30, -9, 40, 36, 11, -14, 26, 30, 22, 10, 28, 12, -6, 6, 25, -14, 10, 7, -8, 6, -17, 10, 12, -8, 22, -23, -20, -10, 5, -57, -7, -20, 37, -8, -14, -54, 31, 56, 25, -25, 24, -47, -28, -2, -26, 37, -7, -30, -22, 16, -17, 4, -4, 12, 12, -23, -13, 11, -40, 18, 11, 5, 5, -17, 40, -40, -7, -27, 25, -10, -25, 33, -28, -29, -34, 38, -9, 37, 20, -1, -11, 23, 5, -24, -18, 8, -13, -13, -22, -10, -15, -32, -9, 47, 36, 25, -37, 2, 32, -25, 3, 21, -22, 18, -38, 5, -17, -37, 30, 6, 25, -11, 31, 4, 23, -3, 19, -23, -4, 47, -41, 42, -37, -9, 36, -43, -27, 3, 23, 12, -12, 9, -16, -32, -3, -29, 26, 36, 7, 5, -44, -10, 34, 55, -8, -18, -50, 2, 21, 11, 16, 13, -3, 8, 2, 8, 7, -23, 32, 43, -31, 19, -11, 5, -53, 37, -26, -8, -34, 19, 42, 19, 17, 33, -25, 19, -20, 22, 29, -12, -34, -22, -6, 0, 0, 16, 29, -17, -39, 2, -33, -14, 6, 6, 41, -9, -25, -1, -21, -41, 4, 8, -22, -33, 23, -3, -1, -59, 7, 8, 27, -28, 34, -14, -40, 15, -15, -6, -3, -11, 30, 38, -34, 1, -37, -30, -40, 6, 20, -33, 3, -23, 37, -49, 47, -21, -29, -13, -11, -4, 18, 45, -16, 19, 33, 26, 38, -6, 22, 5, 29, 3, 0, -30, -14, -24, -28, -25, -7, -2, 38, 34, 14, -8, -30, -6, 5, -9, -15, 24, -4, 16, 35, 11, 10, -13, 46, -7, -16, 2, -19, 25, 12, -61, -3, 58, 0, -30, 36, -7, -30, 5, 0, -24, 31, -18, -42, 18, -12, -37, -18, -30, 24, 20, 32, 34, -28, 11, -34, -17, -8, 5, -2, -9, 12, -27, 15, -33, 0, 35, 26, 2, -13, -5, -46, -9, -16, -38, -26, 7, 16, -20, -30, 46, 11, -57, 44, -19, 17, -33, -22, -14, 34, -37, -44, -29, -16, 27, 42, 11, -17, -8, 5, -46, -49, -9, 11, -16, 1, -13, 27, -25, 11, -10, 4, 3, 2, -15, 2, 10, 9, 1, -36, -8, 31, -41, 60, 23, 17, -53, 9, -19, 1, 27, -18, -67, -19, -5, 53, 16, -19, 16, -18, 21, 24, 5, -11, -23, 36, 9, -4, 46, 13, -25, 25, 40, 5, -25, 12, 21, 30, 13, -20, 19, 64, 3, -33, 0, 23, -19, -33, 19, 10, 35, 0, -4, 4, -30, 39, 12, 31, -22, 13, -8, -5, 1, -32, -25, -5, -1, 2, 32, 42, 20, -1, 37, 24, -48, 3, -24, -35, -30, -25, -13, -1, -30, 1, -25, -38, -15, -19, 12, -25, -37, -12, 19, 16, 28, -1, -14, -3, -41, -3, -17, -13, -36, -12, 4, 6, -3, -29, 0, 2, -13, -15, -11, -7, -24, 23, 0, -40, 18, -26, 3, -17, 30, -20, -26, -1, -30, 10, 40, -20, -6, 26, 17, -32, -4, 5, 10, 18, -33, 17, -25, -19, -7, -13, 27, 43, 15, -18, 28, 12, -32, 41, 33, 32, 6, -6, 22, -18, 12, 0, 9, 50, 5, 40, 3, -9, 16, -30, -1, -8, 3, 12, 11, -35, -8, -43, -21, 8, -4, 44, -27, 7, -6, -19, 42, 36, -5, -15, -47, 13, 13, 36, -13, -67, -46, 27, 30, 16, 4, -27, -5, -34, 5, 37, 12, -34, -35, -50, -35, -2, 29, -14, -11, -11, 9, 18, 14, 0, -6, -43, 3, -3, -7, 2, 12, 37, 36, -14, -18, -30, -18, -3, 15, -21, 17, 15, 9, -38, -58, 2, -21, 13, -16, 50, -6, 4, -34, 1, -16, 12, -2, 23, 36, 13, 34, -26, 39, -41, -24, -32, -39, -24, -51, -2, -5, -26, -32, -14, 10, -19, -39, 27, 21, -3, -13, -24, -22, 13, -22, 5, -26, 15, 2, 31, 43, 18, -48, 43, -9, 36, -10, 43, -9, -47, -19, 5, 47, 27, 39, 18, 25, 36, 22, 25, 8, -5, -28, -80, -27, 21, -35, 40, -2, 14, 30, 2, 13, -11, -8, 33, 28, -29, -13, -34, 0, -3, -13, 0, 40, -19, -32, 38, -12, -72, -49, 55, -22, 37, -10, -43, -40, -27, 43, 10, 0, 59, 11, -38, 30, -1, -34, -7, -10, -22, -14, -22, -6, 18, 5, 1, 12, -23, 39, -15, 30, -3, -20, -49, -2, -15, 46, -10, -43, -8, 40, 29, 13, 34, 1, 7, -25, -22, 13, 1, -33, 0, -6, -22, 39, -13, -19, -18, -15, 3, 54, -16, -19, -23, 41, -29, 25, -48, -1, -4, -10, 16, 0, -53, 21, 19, 39, -13, -5, 9, 26, 2, 10, 18, -59, -4, 22, 24, 10, -6, -22, 19, 14, -17, -30, 2, -45, -60, -31, -30, -15, 16, 14, -51, 11, -47, -12, -27, -27, -13, -15, 26, -13, -37, 25, -21, -29, 44, -29, 24, 21, 35, -33, -9, -3, 34, -17, -19, 16, -47, 36, -14, 12, 32, -51, 5, 15, 17, -25, -23, 54, -60, 16, 11, -8, -18, -6, 37, -22, 40, 39, 6, -34, -13, 5, 27, -6, 37, -7, 8, -16, 33, -22, 25, 2, 13, -30, -18, -18, 12, -2, 34, -21, -6, 25, 0, -29, 2, -8, 9, -14, -30, -6, -16, 44, 13, 11, 42, -7, 1, -18, 0, 22, 8, -2, -30, -1, 38, -11, 5, 15, 18, 15, 44, -53, -25, -3, -21, -10, -25, 1, -6, -7, -6, -33, 13, -16, 6, 19, 37, -22, 49, 9, -28, 32, -34, -9, 23, -32, 13, -24, 17, 1, -22, 15, 35, 28, 7, 25, -13, -58, -26, 38, 20, -39, 17, 20, 27, -16, 13, -30, -11, 10, -18, -33, 13, 9, 30, -20, 2, 7, -35, -13, 51, 11, -10, -9, -34, 34, 40, -23, -13, 46, 1, 8, 39, 19, 27, -12, -27, -17, 44, -20, -24, 25, 1, -30, -23, 47, -6, 6, -8, 9, 2, -28, 32, 31, -25, -49, 0, -4, 16, -13, 7, -3, 20, 25, -21, -14, 10, 11, -48, -24, 35, 19, 12, -32, 34, -28, -19, 13, -25, 1, 5, -11, -37, 27, 5, -36, -9, -19, 34, 11, 16, 7, -11, 44, 4, 23, 15, -27, -31, -35, -3, -28, 19, -20, -17, 1, -34, 9, 14, 30, 25, -23, 22, -3, 8, -22, 1, -8, -59, 28, -43, -32, 5, 12, -46, -17, 1, 38, -25, -47, 50, 29, 37, 1, -10, -53, 28, 8, -33, -12, 18, -2, -15, -8, -25, 16, -20, 26, 24, -26, 44, 6, -30, -5, 24, 35, -26, 13, -17, 12, 32, -36, 19, 26, 16, -5, 9, -25, 10, 10, -25, 3, -31, -45, -12, 21, -29, 3, -29, 24, 24, 14, -54, -33, -13, 3, -9, 1, 27, -8, 30, 0, 38, -19, 37, 17, -15, 8, 8, 16, 16, -5, -10, -21, -57, 1, 35, -53, 30, -10, 40, -28, 5, -23, 1, -18, -3, 47, 16, 10, 43, 41, 41, -57, -3, -24, -49, -30, 16, 0, -20, 21, 9, 37, 20, 30, -17, 54, -35, 9, -9, -8, 15, -14, 4, 26, -13, 5, -21, 2, 34, 14, 17, 20, 19, -41, -6, -18, 25, -13, -4, 7, -4, -79, 5, 14, -27, 18, 29, -18, 8, -39, 24, 8, -24, -27, 0, 6, -6, 36, 8, 49, -51, -5, 9, 33, -19, -12, 19, -20, -4, -6, -37, -52, -6, -23, -2, -19, 55, -53, -11, -6, 21, 9, 75, -18, 1, 10, -52, 44, -35, -18, 27, 4, 32, -22, 4, -14, -13, -29, 43, -5, 22, -54, 13, 27, 2, -14, -13, -8, 8, -36, -7, -2, -29, -43, -18, -35, 2, 23, -6, 19, -10, 37, -17, -32, 6, 13, 32, 16, 25, 39, -8, 21, -22, -6, -34, 51, -17, 20, 14, 13, -30, 40, 28, -4, 4, -23, -24, 41, 35, 20, -29, -21, 13, -3, 21, -39, -21, -2, -24, 34, -3, -26, -16, 31, 10, 8, -18, 29, 23, -15, 17, 41, -19, 26, 2, -28, 27, -5, 23, -24, -19, -7, -24, 3, 4, 45, -7, 2, -30, 18, -5, -8, 8, 10, -28, 36, 11, -18, -52, 42, 0, -4, 14, -35, -9, 20, -8, 40, 14, -43, 31, 14, 36, 23, -6, -22, -17, -28, -7, -4, 1, 18, -48, 4, 33, -17, 20, 9, 29, -15, -42, -15, 11, -11, -17, -19, 30, -28, 19, -4, 26, 0, -19, -2, 1, 15, -23, 39, -9, -23, 3, 28, -34, 8, 12, -30, -12, 16, 20, 39, -9, -53, -22, 10, 6, 8, 30, 7, 31, -36, 3, -20, -25, -16, -14, -24, 6, 8, -5, 26, -38, -13, 32, -39, -19, 44, -19, -30, 2, -19, 29, 5, -45, 4, 15, -13, 36, 11, -12, -32, 33, 6, 16, -5, -13, -7, -11, 14, 21, -32, 5, -4, 36, 57, 5, 1, -19, -8, -23, 10, -27, 30, -46, -21, -29, 33, -58, 4, -4, -30, -8, 5, -7, -15, -16, 28, -17, 20, 32, 16, 0, 16, -45, -9, 18, 38, -18, 8, 32, -3, -34, 18, -9, 13, -42, 9, -40, 5, 5, 28, -7, -17, 33, -16, -7, 46, -27, -31, 16, 7, -9, 24, 47, 30, 21, 0, 15, 20, -30, -1, 5, -6, 26, 25, -17, 16, -19, 5, -22, -22, -15, 22, -1, 23, -1, -18, -10, 20, 10, 32, -8, 22, -13, 1, -46, 0, 18, -3, 42, 24, 25, 0, -1, -46, 17, 5, -19, 18, -7, -11, -43, 12, 8, 20, -14, 33, 13, -23, -26, -30, 30, 4, 1, -15, 45, 26, -16, 15, -13, -20, -26, 28, -6, 21, -24, -12, -33, -26, -11, 34, -27, 44, -46, 34, 7, -17, 29, -14, -20, -48, 28, 7, 22, -37, 14, 0, 19, -3, 32, 30, 31, -17, 29, -13, 45, -17, -23, 42, 2, -31, 4, 28, -13, -2, -21, -22, -26, -10, 24, 0, -54, -11, 36, -33, -28, 30, -28, -19, 21, -20, -50, 1, 11, -22, -6, 27, -14, -2, 16, -43, 24, 14, -3, 24, 32, 39, -5, 19, 38, -14, 5, -29, 16, -27, -22, -21, 1, 21, 18, -21, 8, -14, -1, 12, 27, -9, 43, -35, -22, -26, -3, -25, -6, 15, 10, -34, -4, 6, 31, 24, 0, 15, -15, 46, -40, -31, 44, -12, -27, 28, 20, -12, 13, 26, -12, -28, -32, -22, -10, -8, -12, 3, 33, 33, -4, 4, 5, -18, -11, 29, -16, -2, 22, -45, -7, 38, 1, -12, -33, 0, 1, 13, -6, 27, 13, -7, 38, -23, -12, -43, -28, -21, -27, 6, -15, -15, -15, -7, -6, 10, 23, 49, 1, -8, 34, 26, -54, 5, 6, -21, -50, 44, 9, -18, -32, -12, -19, 29, -11, 6, -35, -6, 30, 5, 3, 9, 11, -43, 35, -16, 4, -5, 22, -41, 8, 21, -3, 4, 51, -3, -15, -3, 20, -7, -12, -17, 29, 10, 1, -28, 28, 18, 6, 20, -9, 7, -17, -12, 1, 12, -17, 44, 43, 30, -12, -19, -9, 5, -32, 7, -26, 11, 3, 24, -74, 54, -25, 1, 15, 33, -1, 14, -31, -17, -2, -53, 5, 32, -7, 4, 29, -41, 18, 4, -37, 7, -37, -16, -13, -14, -16, -24, -1, 1, 12, -37, 15, 30, 43, -6, 21, 7, 11, -14, 8, -11, -25, -14, -19, 10, 21, 14, -30, 38, 30, 6, 40, 14, 34, -51, 2, 52, -8, 1, 5, -13, -12, -54, -53, 13, -6, -16, 25, -15, 19, 16, 10, -22, 24, 13, 16, -48, 38, 10, -25, -4, -1, 8, -12, -25, 34, 0, -17, -39, -22, 8, 23, -15, 24, -12, -35, 12, -28, -18, -48, -25, -11, 3, 26, 1, -2, -57, 34, -14, 20, -35, 13, -33, 29, -18, 23, 0, 26, 43, 9, -3, -5, 52, 8, -11, -27, 11, -6, -34, 23, -18, 49, -45, 30, 9, 3, -50, 11, 24, -36, -13, -26, 25, -21, 0, -16, -11, -8, -23, 15, -34, 8, 18, -12, 19, 51, -21, 8, 1, 2, 14, -1, -14, -12, -10, -34, 23, 4, 21, 40, -2, -12, -38, -29, 4, 6, 0, 25, 2, 51, -26, -4, 56, 11, 23, -2, 10, 11, -4, 24, -25, -48, 44, -7, 45, -3, 3, 18, 34, -10, 21, 29, -19, -12, 14, -2, 20, -19, 49, -8, 2, -3, -21, 0, -32, 39, -16, 23, -25, -3, 10, 21, 22, -13, -13, -32, 34, 17, 5, 47, 37, 9, -1, 34, -17, 15, 8, -44, 6, 30, -24, 37, -9, 8, -35, 46, -20, -8, 25, -29, 18, -20, -26, 22, 42, 34, 10, 34, 19, -35, -55, -15, 37, -29, -11, -4, -1, -21, 6, -47, -6, -5, 9, 6, -52, 8, -30, -23, 22, -11, 51, 32, -13, -36, -11, 47, 4, 21, 36, -25, 11, 7, -16, -1, -33, -16, 1, 10, -26, 28, 27, -12, 13, 3, 25, -16, 28, -4, -6, 59, 7, -43, -1, -24, -54, -26, -12, -4, -65, -21, -29, -12, 25, -22, -5, 25, 15, -28, -1, 23, -7, -17, 20, 22, 27, 27, -4, -4, -41, 11, -8, 9, 0, -9, -2, 26, 42, 41, -1, 17, -8, -9, 2, -16, -9, 11, -12, 6, -15, -10, -33, -11, 10, 34, -5, -10, -25, 29, 50, 14, -17, -6, -26, -62, -26, 1, 53, 21, -26, -25, -45, -27, 30, 22, -18, -32, 17, 51, 10, 38, 22, 2, 8, 1, -5, 14, -46, 32, -1, -23, -20, 18, 38, 23, -15, -42, 25, -16, -42, -40, -30, -22, -14, 9, -41, -8, 22, -27, -34, 28, -40, -71, -2, 3, 20, 2, -57, -10, 32, -23, 50, -34, -20, -44, 10, 21, 47, -29, 7, -8, -27, -2, 14, -2, -23, -73, 11, -18, 69, 51, 21, -12, -8, -32, -33, 33, 19, -20, 21, -15, -7, -31, -22, 24, -42, 23, -35, 19, 39, 48, -40, -20, 23, 21, 42, 18, 8, 14, -34, -38, -15, -33, -23, -24, -44, -29, -7, 42, 7, -23, -13, 34, -41, -15, -17, -8, -34, 27, -24, -9, -26, 29, -15, 34, 21, -30, -71, -12, 17, 36, 27, 0, 7, 14, 44, -37, -16, 3, -13, -4, -21, -1, -23, 35, -35, 12, -12, -3, 14, 27, -21, -4, 20, 7, -45, -1, -36, -39, -22, 20, -42, -21, -13, 24, -13, 35, -6, 12, 50, 7, -69, -40, -4, -52, -27, 50, 40, -17, 6, -22, -1, 8, 10, 10, 10, 17, 39, -23, 31, 12, -7, -59, -67, -3, -23, -24, 25, -21, 28, -34, -5, 12, -18, 12, 26, -33, 3, 33, 10, 62, 17, -26, -56, -14, -77, 9, -9, -4, -27, 52, -3, -15, -9, -6, 12, -1, 8, -24, -47, 2, -21, 14, -33, 5, -31, 2, 29, -23, -39, -12, 27, 2, 9, 42, -14, -7, 23, -7, 12, 29, -32, -35, -23, 8, -39, -28, -18, -16, 16, -31, -23, -36, 14, -5, 9, 0, 3, -10, -12, 41, 12, -31, -25, -17, 25, 49, 25, -21, 37, 16, 10, 17, -2, -5, 40, 13, 16, -8, 28, -64, 31, 0, 28, -19, 39, -47, -30, 5, 17, 32, -31, 31, 4, -9, 44, -11, 47, -44, -28, -29, 25, -15, 3, -7, -13, 25, -45, -22, 14, -37, 19, -20, -16, -32, 0, -35, 1, 16, 37, -38, -29, 27, 19, 35, 15, 6, -34, -74, -1, -16, 6, -9, 20, 53, -43, -18, 6, -61, 17, -42, -20, -42, -15, 7, 41, -35, 3, -10, 15, -17, 5, 6, -18, -8, 57, 35, 7, -54, -44, -10, 27, -9, 5, 13, -12, 11, -9, -42, -14, 0, -13, 42, 17, 31, 12, -7, -55, 22, 7, 28, 8, 24, 2, -18, -39, 33, -18, -15, 19, -39, -52, 28, -4, -36, 25, 21, -9, -9, -18, 11, -43, -7, -35, 36, 9, -24, 39, 25, -29, 28, -14, -32, -14, -19, -65, -34, -19, -44, 32, -28, -14, -9, -45, 33, 2, -24, 2, 43, -62, -37, -12, -38, 28, 57, -4, -34, -13, -38, 41, -33, -21, 21, -15, 37, -35, -16, 54, -14, -89, -8, -21, -21, -48, -11, 12, -33, -9, -30, -13, 7, 38, -45, -25, 31, -26, 42, -23, -5, -13, -12, -2, -21, 37, 13, -28, -19, -2, 20, 38, 31, 12, -52, -13, 10, -17, -55, 16, -26, -33, 14, 25, 21, 30, -71, -17, -1, -30, -9, -20, 25, -17, -8, -4, -16, -29, 63, -48, -20, -28, -29, -32, -26, -6, 24, -18, 16, 9, -27, -2, 22, 9, 9, -3, 22, -71, 22, -12, -21, -18, -29, 46, -22, 23, -5, 10, 53, -19, -29, 2, 44, 9, -2, -7, -20, 17, 28, -12, 6, 10, 31, 15, -35, -26, 45, -23, -25, -24, 21, 32, -61, -44, 20, 24, -23, 19, 2, -13, 31, 5, 19, 1, 30, 3, 21, 21, -27, 2, -8, -10, 35, -27, 6, -19, 34, -19, 1, -14, -12, 13, -38, 15, -84, 8, -5, 5, 39, -16, -20, -44, -47, -21, 5, -11, -32, 7, 9, -36, -21, -35, -14, -13, 25, 5, -45, 37, -15, 10, 25, 62, -42, -43, -13, 24, 2, -20, -15, 4, 4, -13, -32, 22, -18, -45, -36, 9, -11, 11, -3, 25, 1, 27, -90, -9, -5, 25, 45, -11, -38, 13, -14, -14, -9, 10, -39, 6, 5, -35, 14, 6, -13, -31, -17, -20, 16, -5, -24, -39, 0, -2, -23, 28, 50, -29, 39, -22, -10, -32, -1, 52, 11, 24, 16, 9, 0, 65, 5, -20, -14, -17, -44, -18, 3, -31, 24, -13, -3, -17, -23, -3, 48, -2, 5, 21, 29, -11, -1, 4, 28, 39, -39, 21, -36, -5, -15, 27, -5, -11, 13, -44, 40, 1, -24, 4, -10, -63, -4, -21, 45, -25, -41, -41, -8, -47, -7, -32, -1, 41, 26, -42, -39, -69, -4, 27, 12, -14, -11, 1, 28, -24, 25, 0, -12, 9, 13, -54, -36, 29, 3, 2, 4, -49, -56, 12, -17, -48, 28, -31, 11, -22, 24, 8, 9, 21, -45, -1, 39, -5, 11, 16, -23, 37, 16, 22, 9, -21, 22, 5, 20, 37, 20, 43, 20, -6, 29, -8, -9, 35, 34, 9, 2, -28, -11, 2, -23, 23, -24, -9, 24, 8, -11, -20, 31, 15, -21, -11, -16, 13, 31, 39, 6, 1, 38, -49, 7, -42, 15, 31, 30, -44, 1, -25, -28, 11, 30, -21, -65, 27, -19, 22, 7, 5, 21, -9, 19, -17, 14, 18, 18, 13, 35, 1, 23, -19, 8, 7, -10, 19, -28, 20, 17, 15, -32, 25, -21, 1, 29, 19, -42, 20, 10, -29, -60, -1, 23, 9, -36, 5, -1, -23, 3, -16, -12, 34, -35, 9, 5, -11, -16, -18, 32, -5, -9, -38, -18, -26, -37, 0, 13, -2, -32, 29, 40, 12, -12, -11, -55, 3, -42, -40, -1, -4, 15, -25, 43, -3, -17, 23, -29, 21, 14, -46, -39, 39, 9, -32, 37, -14, 25, 17, 7, 8, 12, 9, -8, -12, -55, 10, -19, 25, 35, -18, 6, -45, -28, -8, -24, 39, 8, 1, -16, 20, -12, 19, 29, -10, 31, -3, -20, -1, 38, -1, -10, -28, -32, -54, -5, 27, -25, -38, 35, -10, 9, 27, -9, 40, 25, 5, 1, 1, -39, -7, 38, 15, 9, -27, -28, -48, 46, -20, 9, 31, 19, -48, -15, -38, -37, 42, -7, 22, -9, 11, -38, -24, -2, -19, -11, 35, -29, -33, -2, -31, -2, 46, -26, -30, 39, 25, 5, -28, -16, -53, -23, -8, -43, -8, -10, 21, -12, 23, 42, 4, -29, -17, -47, -32, -42, 42, 48, 24, -49, -17, -11, -33, 65, 5, -55, -6, -1, 0, -8, -25, 44, 39, 13, -30, -2, -15, -33, 0, 17, -17, -21, 27, -57, 0, -13, 32, -14, 32, 4, 1, -4, 24, -24, -20, -36, 3, -25, 6, 27, -25, 2, 11, 24, 5, -30, -20, -6, -13, -37, 16, 16, 16, 50, 0, -33, -4, -8, 34, 2, 25, 11, -10, -35, 32, 1, -33, 2, 5, -7, 9, 12, -43, 5, -17, -34, 4, 13, 15, -26, -9, -27, 32, 11, -18, 15, 30, -25, -1, 0, 46, 3, 21, 18, 10, 14, -2, 58, -28, 51, -22, -8, 32, -7, -14, -25, 16, 27, 11, -26, 34, -4, 23, 1, 34, 25, -50, -6, 31, -27, 32, -8, 13, -8, 32, 20, -29, 12, 35, -8, -7, 4, 6, -35, -5, -34, 14, 7, -38, 15, -50, 15, -38, -8, 8, -30, 26, -33, 35, 59, -19, 6, 2, 19, 19, 26, -27, 37, -9, -5, -6, -19, 11, -24, 48, -30, -12, 62, 10, 36, -23, 19, 24, 12, 22, 7, -16, -25, -21, 2, 5, 29, 24, -18, -18, 30, -10, 47, -12, -21, -24, -6, -4, -6, -12, -6, -35, -17, 11, 0, 2, -3, -2, -46, -6, 27, -23, 31, -48, 32, 10, 21, 14, 29, 18, -5, -34, 13, -15, 16, -13, -67, 24, 12, 14, 6, 6, -29, 17, -9, 8, 14, -25, -41, -10, 37, -41, -19, -24, -32, 20, 23, -36, -39, 34, 7, -12, -25, -37, 38, -10, 9, 28, 32, -21, 25, -45, -5, -10, 21, -19, -25, -8, 0, 24, 49, 5, 3, 1, 9, 46, 7, 5, 23, -26, -25, -15, -23, 27, -28, 43, 6, 5, -2, -28, -53, -12, -46, 17, -44, 6, 22, 37, -9, -10, -19, 18, -77, -1, -23, 21, -37, 49, -6, -3, -26, 15, 10, 25, -15, -33, -11, 15, 20, 1, 35, 47, -7, -1, 15, -25, 5, -39, -20, 13, 10, 14, 9, 16, -45, -42, -45, 16, -19, 11, -4, 5, -18, -5, -8, -26, 17, 35, -27, 27, 50, -42, -20, -31, 44, -23, -33, 3, -27, -17, -13, -45, 0, -45, 32, -18, -29, 4, 12, 17, -43, -11, 34, 17, -9, -25, 1, 24, -41, -10, 13, -4, 3, 21, -4, 20, -24, 20, 11, -41, -27, 17, 2, 6, -46, -48, 26, -3, 23, 21, 10, -31, 1, 33, -11, 28, 25, 9, 2, -7, -52, 19, -30, 25, -11, -49, -6, -32, -18, -28, 10, -17, -11, -10, -11, -46, 22, 16, } +#define IP2_BIAS {-25, -21, 5, 25, 5, -16, 21, 72, -15, -7, -14, 19, 4, -10, -11, 91, 50, -33, 55, 63, 16, -82, 29, -22, 51, 32, -20, 35, 11, -49, -37, 8, 37, 30, 26, -46, 84, 74, 109, -14, 82, 6, 77, 26, 37, 17, 54, -12, -4, -90, -30, 108, 39, 16, 14, 114, 19, -23, -2, 16, 17, -41, -39, 52, 22, 9, 15, -18, -13, -21, 61, 52, -35, -34, 3, 95, -2, 30, 74, -43, 14, -70, 56, 47, 13, -19, 13, 36, -42, -14, -38, -24, 22, -11, -7, 27, -19, -3, 43, 39, 25, 108, 115, 25, 50, 86, 6, 26, -14, -13, 56, -11, 17, -42, -59, 58, -20, 33, 89, -55, -28, 47, -54, 18, 5, 43, -72, 54, -17, 75, 54, -27, -78, 27, -2, -20, 49, 21, 13, 53, 40, -40, 69, 47, } +#define IP3_WT {16, 25, -13, -3, -30, -15, 33, -9, -21, -9, 30, 47, 40, 23, 6, 15, -3, 15, -24, -6, 5, 37, -43, 53, -27, -37, 12, -20, -61, 9, -22, 19, -41, -9, -1, 38, -4, 8, -40, 7, -25, 15, -11, 2, -11, 24, 32, -31, -18, 36, -7, 7, -6, 57, 7, 31, -21, 33, -18, 24, -21, 18, 46, -52, -40, 32, 17, 12, 13, 36, -14, 8, -7, 28, 32, 15, -18, -21, -23, 46, -20, 25, -6, 25, 14, 21, 24, -35, -17, -4, 36, -52, -28, 2, 11, -32, -2, -21, -14, 21, -1, -8, 22, -23, -25, -34, 3, -30, 4, -5, 15, 29, -11, 4, -6, 0, 22, 28, -21, -21, 47, -27, 14, -9, 30, 14, -54, 17, 29, 16, 31, -17, -45, -24, -46, 33, -16, -5, -7, 22, -13, -2, 26, 25, -42, 28, -46, 36, -11, -12, 1, 22, -36, -14, 28, -12, -9, 30, 9, 17, 49, 27, 11, 38, 27, -10, 23, 4, 48, 9, -19, 6, 10, 12, -19, 15, -47, 9, 21, 4, 35, 42, 20, 21, -14, -19, -5, -15, 24, 8, 43, -17, 46, -25, -34, 23, 20, 5, 34, -15, -9, -13, -36, -16, -38, -28, -33, -23, -18, -32, 21, -21, -1, -32, -18, 22, 19, 17, -29, -23, 9, -20, -5, 13, 14, 11, 34, 35, -14, -19, 37, -9, -7, 25, 36, -37, -11, 6, -6, -32, 1, -4, 35, 27, -11, 28, 12, 31, 39, -22, 18, 7, -6, 26, -13, -4, -41, 21, 0, -41, 31, -30, -9, 7, 7, 33, 29, 38, 26, -40, -40, -9, 2, -7, -8, 24, 18, 27, -18, 6, -27, -11, -38, -22, 7, -38, 6, 8, 22, 11, 3, 4, 6, -30, 11, -25, -45, 8, -17, -40, -29, -29, -15, -25, -31, 2, 7, -26, 6, -26, -10, -55, 28, -32, 1, -15, -6, -5, -31, -32, -44, -28, -25, 11, -36, -23, -4, -15, -18, -8, -23, -52, -15, -9, 5, 23, -4, 26, 39, 20, 24, 28, 18, -18, -52, 9, -7, -5, -20, 23, -16, -28, -41, 0, -47, 6, -36, -42, 19, -6, -23, -58, -45, 49, -3, -9, -7, 4, -17, -38, -9, 2, 16, 22, 0, -30, 20, -40, 4, -61, -18, -36, 13, -30, -23, 4, 39, 31, -32, 7, 58, -31, 15, 26, 0, -20, -4, -18, 22, -17, 7, -35, -22, 11, -4, -28, -40, 16, 22, 13, 5, -22, 9, -8, -4, -25, 17, -9, -16, -40, -31, 18, -36, -6, 33, -23, 7, -11, -22, 24, 27, 12, -11, -3, -2, -1, -16, 35, -39, -2, -35, 14, 14, 23, 50, 29, 13, 7, -44, -71, 2, 9, -31, -27, -23, -4, -5, -15, 12, 15, -8, -14, -42, -29, -27, 19, -1, 0, 13, 26, -39, 24, 56, -20, 36, -28, -3, 19, 23, 32, 0, 21, 5, 44, 43, 36, -44, 35, 21, -17, -63, -19, 30, 13, -2, 23, -36, 7, 29, 20, -3, -14, 28, 8, -50, 24, 12, 30, -32, 38, 9, -44, 44, 10, -37, -52, -38, -52, 28, -3, -29, -38, -27, -7, -3, -9, -2, 19, 24, -33, -8, 9, -6, 13, -26, 21, -11, 2, 17, 29, 25, 16, 7, -45, 2, -26, -1, -9, -4, -22, 26, -16, -23, -13, -9, -5, -19, 4, -12, 5, 44, 2, 14, -28, -43, -5, 25, -2, 36, 34, -19, 32, -13, 20, 40, 9, -41, -3, -26, -5, -24, -4, 54, 12, -41, 0, 10, 3, 26, 22, 52, 10, -10, -12, -24, 36, -8, -10, 20, 6, 36, 23, -8, 7, 37, 12, -28, -4, 13, -44, 4, 36, -4, 45, -5, 12, 40, -55, 2, 13, -16, -30, 38, 30, -51, -1, 43, 15, 8, 8, 31, 0, -19, 35, -13, -37, -13, -12, 48, -28, -25, -15, -1, -43, -40, -2, -7, 16, 18, 23, 2, 44, -26, 23, 23, -4, -49, 6, 48, 6, 30, 17, -20, -11, -19, 32, -22, 12, -28, 19, -20, -32, 4, -37, -24, -9, -37, -1, 36, -13, 7, 44, -24, 29, 9, -14, 7, 27, -16, -28, 7, -11, 4, -34, 4, 10, -1, -24, 36, 38, 22, 2, -25, -12, 6, -59, -37, 7, -40, -8, -21, 34, -24, -48, -5, -9, 51, 20, 44, 31, -15, 46, 57, -56, -28, -1, 3, 9, 7, 37, 14, -7, -14, 15, 43, 13, -28, 46, 40, 9, 35, 3, 6, 13, -27, 10, -6, -30, -13, -14, 22, 36, 14, -20, 1, 25, 36, 56, 20, 36, -14, -28, -40, 22, -40, -2, -11, -33, 33, 22, -32, 34, 6, 19, -1, -1, 21, 22, 34, 22, -15, 24, -1, -33, 54, 29, -44, 21, -25, 24, -27, -23, -40, 23, -28, 17, 3, -1, -3, 12, 33, 32, -38, -51, 14, 9, -3, 27, 11, 2, 24, -26, 10, -10, -41, -43, 45, 24, -57, -49, -7, 1, -44, 17, -9, -16, -6, -26, 2, 11, -9, -18, -11, 20, 29, 9, 4, -8, 11, 17, 39, -9, 33, 6, 1, -41, 12, -41, -2, 33, 9, -1, -17, 6, 12, 33, 9, 28, 16, -11, -37, 19, -25, -14, -12, -9, -17, -34, 20, -31, 3, 22, -11, 12, 13, 49, -3, -31, -17, 19, 13, -28, -22, -13, 33, 29, 4, -33, 14, 0, -20, 37, 56, -22, -5, -39, -12, 24, 29, 20, 35, 17, -1, -18, 0, 34, -26, -10, 11, -42, 55, 23, 9, -14, -29, -28, -69, -11, -16, 3, -7, 38, -40, 35, -21, 34, -3, -3, 23, 24, -37, 36, -7, -18, -11, 7, -22, -5, -39, -73, -23, -19, 3, 25, -48, -9, 26, -47, 28, -37, -11, -25, 7, -22, 27, 18, -33, 34, -6, -7, -3, -9, -15, 24, 35, -2, 42, -16, -4, -32, 25, -29, -42, -18, 14, -76, -33, -12, -17, 28, -7, -12, 8, 31, -50, 5, 35, 8, 8, 44, -18, -11, 38, -5, 0, 5, -33, 5, -18, -22, 24, 19, -25, 9, 11, -2, -5, -21, 6, 1, -15, -46, -14, 2, 43, 25, -30, -23, -29, -6, -2, -9, 51, -28, 11, -18, 8, -27, 26, -23, -35, 15, 26, 7, -18, 9, -27, -40, -24, -42, 22, 19, 25, -27, 1, -7, 37, 4, 13, -39, -51, -26, 50, -49, -16, 8, 41, 2, 5, 10, 2, -20, -38, -9, -15, -32, 33, -6, 15, 0, -6, -10, -29, 32, -3, -18, -8, -14, -32, -6, -4, 15, 22, 5, -32, -4, -25, 13, -21, -45, 20, 1, -5, 12, 10, -31, 6, -2, 4, -40, -12, -31, 24, -28, 28, -27, -34, -40, -25, 20, -58, -21, -27, 29, -39, 29, -10, 24, -11, -1, -24, -20, 33, -43, 18, 37, 1, 12, 18, 38, -32, -24, -9, -17, -5, -31, 0, 4, -14, -5, 0, -28, -15, 10, -19, -3, 7, -12, -14, -60, -6, -28, 16, 10, 22, -9, -32, -39, 16, -15, -20, -29, 31, -26, -13, 18, -10, -19, 18, 25, 13, 49, -14, -4, -10, 32, 10, -14, 42, -51, 1, 25, 17, 26, -17, -9, 13, -20, 31, 13, -6, 31, -39, 13, -25, 20, 25, -5, -25, -16, -24, 18, -35, -30, -3, 5, 16, -26, 22, 19, 0, -1, -15, -31, -23, -35, -28, -67, 18, -19, -2, -55, 20, -2, -22, -33, 5, 30, -44, 41, -12, 21, -36, -42, 8, 32, 14, 34, -18, 26, -15, -15, -4, -19, -21, -4, -5, 55, 13, -48, 23, -34, 22, -18, -24, -2, 13, 45, 14, 3, -22, 29, 23, 58, 15, 38, -11, 19, 25, -20, -5, -10, 14, -25, -6, -11, 14, 24, -70, -4, 12, -22, -17, 48, -5, 46, -1, 54, -8, 19, 4, -23, 12, -29, 2, 56, -3, -28, 26, -29, -20, -27, -5, 28, -21, -18, 35, -15, 39, 10, -2, 41, 0, -24, 8, -5, -12, -29, 52, 0, -27, -7, -17, 7, 1, -5, 9, -29, 47, -62, 21, -5, 5, 13, 23, 5, 15, -24, 30, 24, -42, 9, 10, 8, -9, -8, -29, 1, 14, -18, -48, 15, 41, -11, -13, -27, -19, 35, 31, -4, -4, 6, -36, -28, 21, -8, 0, -29, 35, 51, 19, 26, 45, 28, -34, 50, 30, -45, -13, -39, -11, -39, -48, -7, 26, 6, -41, 45, 5, -12, -6, 45, -30, 18, 7, -37, 24, 29, -29, 16, -20, 5, -25, 18, -47, 26, -8, 36, -37, -30, -38, 41, 10, -30, -3, -61, 21, 20, 15, 31, -38, 3, 15, -53, -19, -2, 28, 52, -30, -37, -1, -25, -34, 43, -53, -10, 3, 9, 15, 20, 26, -13, 22, -20, -4, -3, 13, -37, 3, -27, -15, -34, 29, 8, 18, 41, 8, -74, -18, -32, 52, -22, 41, -29, 10, -14, -14, -11, 38, 28, -45, 25, -27, -20, 15, -4, 20, 31, 1, -10, 32, -11, 19, -30, 1, 26, 31, 45, 6, -20, -29, -17, 28, -13, -4, -6, -13, 22, -8, -2, -22, -10, -39, -20, -36, -27, -32, -37, -33, -13, 52, 6, -11, -23, 22, 5, 13, -3, 8, 9, 16, -44, 26, -27, 2, -51, -32, 13, -21, 47, -18, 20, -37, 12, -54, -6, -16, -7, -45, 2, 28, 22, -6, -10, 44, 36, -6, 52, -24, -9, 26, 35, 22, -2, 13, -18, 26, -5, -4, -16, -22, 26, 21, 48, 6, 0, -14, -4, 30, 9, 28, -21, 16, 9, -28, -47, -31, 35, -33, 32, 49, 14, 12, -15, -37, 4, 27, -37, 8, -4, 55, 38, -31, -46, -29, -52, -5, 1, -11, -4, -34, -40, -78, 34, 12, 11, -14, -3, 0, 17, 64, 3, 42, -20, -21, 27, -29, 15, -36, -35, -29, -11, 2, 17, 13, -19, 25, 24, 8, 18, -49, -33, -40, 14, 9, -11, 63, -36, 16, -25, -42, 28, -16, 8, 45, -36, -49, -18, -80, 3, 30, 13, -41, -23, 36, -50, -16, -17, -18, -25, -51, 11, -64, 41, -1, -25, 1, 3, 51, -10, 3, 11, -29, -30, 45, 20, 18, 30, 15, -27, 7, 14, 0, 25, 21, 29, -46, 31, 10, 15, 45, 2, 54, 13, -22, -36, -22, 59, -29, -18, 76, 31, 24, -34, 7, -39, 19, 8, 32, -22, 24, 28, 1, 41, -12, 17, 6, 44, 20, 3, -37, 23, 50, -42, 2, -66, 20, -3, 10, 9, -28, 18, -19, -30, 7, 7, -13, 22, -7, 27, -40, -31, 18, 10, 20, 45, 36, -32, 10, -15, -8, 16, 23, -33, -18, -17, -3, -3, 26, -36, 9, 57, 30, 7, 23, -27, 26, 28, 12, 33, 36, 30, 2, 5, -36, -31, 12, -27, -7, -18, -39, 13, 21, 22, -52, 7, 3, 8, -9, -30, -60, -14, 25, 19, 13, -25, 22, 7, -30, -22, 13, 11, -11, 20, 30, -44, 25, 6, 21, 15, -9, 31, -6, 26, 18, 1, 15, 0, 25, -10, 19, -24, 49, -13, -34, -18, 41, 31, 1, 40, 41, -19, 19, 47, -12, 9, 1, -2, -26, -10, -21, -37, -24, -7, -53, -4, 47, 0, 21, 34, -20, 3, -55, 19, -81, -30, 38, 7, -15, -10, 19, -4, -25, -16, 17, -11, -9, -32, -16, -23, 20, -21, 14, -35, -7, -8, 37, 41, -40, 20, 37, -37, 20, 21, -42, -24, -47, 38, 37, -26, -5, -55, -28, 20, -10, -24, -35, 6, -43, 35, -17, -23, 4, -50, -4, 4, 15, -23, 6, -9, -17, -2, 1, 4, 25, -9, 26, -9, -21, 18, 20, -17, 17, 22, -35, 0, 32, 13, -10, -2, -32, 23, 2, -13, 18, -26, 14, 10, 8, 25, 4, 33, -7, 1, 2, 26, -8, 43, -2, -7, -24, -44, -32, -2, -26, 8, -5, 55, -28, -3, -24, -42, 4, -37, -10, 45, -24, 28, -42, -20, 4, 8, 17, 23, 0, 23, -2, -31, -19, -22, 16, -25, 4, -5, 27, -5, 9, 23, -16, -27, 14, -14, -27, 37, -13, -14, -1, -2, 14, 7, -10, 34, 26, -24, -2, -17, -20, -34, -12, -23, 5, -8, 13, 12, -12, 20, -11, 1, -43, 1, -37, -10, 10, -37, -14, 37, 2, -48, -37, 28, -29, -24, -9, 22, -3, -25, -4, 2, -38, 14, 2, 6, -47, 11, -34, 15, -17, 0, -6, -17, 18, -25, 19, -36, 4, 20, 29, 53, 23, 31, -22, 19, 24, -34, -7, 14, 20, 35, 10, -25, 15, 10, -11, 23, -17, -9, 31, 12, -18, -25, 40, -57, -50, -48, -35, 20, 21, -41, 36, 21, -43, 5, 30, -5, 24, 0, 17, 7, -44, -12, -72, -16, -13, 41, -61, -7, 11, -22, 34, 14, 8, -49, -11, 4, -13, 32, 20, 23, 29, 47, -3, 1, 1, -4, -5, -16, -11, -40, 6, -26, 18, -47, -5, -3, -16, -9, 44, 45, -15, -36, 15, -49, -5, -14, 0, 9, -32, -15, -5, 12, 36, 1, 64, 28, -37, -29, 0, -14, 45, -66, 35, 17, 3, -20, 33, -5, 26, 45, -15, 1, -2, -23, 54, -19, 24, -11, -11, 3, -7, 35, 28, 14, -21, 17, 40, -18, -31, 21, -62, -40, 8, 29, 46, -12, -15, 16, -3, 0, 11, 29, -40, -22, -32, 5, 13, 14, -1, 32, 10, 45, -30, 46, 5, 32, -21, -66, -54, -5, -46, -40, 20, 43, -22, -10, 8, 27, 38, 19, 17, -41, -17, 36, 17, 17, -37, 4, -20, 7, -19, -27, -26, -10, -5, -44, -3, -28, 15, 12, -28, 28, 1, -29, 30, 0, -22, -14, 24, -52, 17, 24, -23, 9, -9, -11, -12, -24, 7, -35, -1, 19, -2, 13, 34, -11, 55, 19, 4, 19, 2, -3, -7, -17, 27, -20, 17, 5, -13, -36, 9, -30, -1, -48, -61, -5, -8, 9, -4, -52, -2, -11, -2, -1, 27, 20, -18, 7, -19, 12, 19, -21, 10, 29, -14, 18, -8, 25, 33, -23, -32, -25, 28, -1, 34, 0, 4, -12, -8, 6, 2, 22, 10, 42, -24, 27, 18, -10, 37, -26, -12, -40, 18, 24, 6, -9, 0, -43, 1, -17, -12, -3, 19, -13, 29, 31, -7, 2, -15, 28, -26, 8, 32, 30, 0, 25, -22, -13, 16, 14, -46, -54, -25, -33, -23, -44, 23, 5, -32, -9, 8, -4, -13, 7, 13, -21, 30, 14, 51, -44, 35, 8, 29, -5, -37, -26, 32, 13, 43, 26, 12, 18, -15, -32, -28, 16, -8, 37, 0, -35, -29, -12, -23, 17, 12, 38, -17, 16, -54, -19, -38, -15, -4, -17, -23, 13, -39, 43, -75, 63, 39, -17, 41, -3, 25, 38, 30, -8, -5, 0, -2, -12, -52, 22, -2, -5, -28, -10, -24, -25, 12, -29, -64, -26, 2, 19, -12, -10, 25, 50, 58, 31, -18, -21, -7, -15, 17, -4, -14, -27, 3, -46, 21, 42, 12, -15, -7, 5, 41, 30, 37, -1, 36, 20, 33, 11, -9, 15, -11, -48, 33, -29, 3, -11, 29, 8, -18, 19, 21, 29, 6, 8, 40, -2, -3, -1, -1, 11, 19, 29, -31, -23, 34, -28, 31, -12, 13, -7, -2, -1, -9, 31, 1, 23, 4, -51, -24, 45, 4, 20, -35, -34, -24, -11, -2, -37, -16, 8, -55, 25, 20, -44, 30, -18, 32, 18, -8, 4, -48, 8, 17, 31, -8, 20, -24, 0, -12, -3, -71, 8, 7, 39, -41, 11, 21, 7, -55, -6, 3, 29, 8, 16, 7, -43, 25, 25, -1, -5, 5, -20, -23, 12, -18, -27, 44, -44, -30, -25, 30, -13, 29, -35, 20, -3, -3, -35, -16, 35, 7, -16, -9, 15, -16, 27, -19, -41, -14, -2, 42, -3, 17, 11, 8, -9, -4, 5, -25, -25, -19, 30, 5, -32, 24, 32, 35, 11, -18, 21, 19, 21, -39, 34, 31, 19, 23, -17, 33, -5, -15, -8, -30, 10, 31, 41, 16, -27, -17, 26, -29, 46, 0, 3, -47, -19, 31, 12, -11, -8, 22, 25, 28, -21, -6, 14, -38, 34, 17, -50, -24, -4, 32, 44, -7, -9, 18, -21, 14, -8, 28, -17, 6, -1, 54, -27, -16, 35, 14, -19, -69, 4, -13, -29, -31, 30, -30, 19, -15, -23, -39, 16, -6, -2, -3, 11, 18, 17, 8, 8, 26, -24, -8, 2, -12, -50, 26, 10, 17, 26, -6, 31, 19, 2, 16, 8, 36, -12, 33, -61, -21, 5, -70, 22, 15, -24, -17, -33, -28, -27, 9, 13, -9, 41, -3, -30, -18, -66, 5, -16, -20, 5, -25, -6, 12, 5, 4, 18, 43, -10, 21, -18, 10, -43, -4, 13, 15, 6, 3, -35, -25, 8, 6, 19, -66, 5, 9, -35, -4, -49, 43, 14, -2, 41, 3, 5, 41, 7, 57, -33, 13, 0, 52, -50, -6, -33, 57, 2, -10, 5, 20, 3, -12, 35, 29, 21, -35, -13, 25, 28, 23, 40, -46, -9, -16, -36, -34, 34, 5, 5, -36, -36, -26, 28, 41, 20, -21, -1, -6, -36, 12, -8, 24, -3, 0, 66, 40, -10, 18, -35, -13, -35, 1, 6, 4, 30, 36, 21, -7, -25, 51, 3, -26, 32, 4, 5, 9, -13, -17, -4, 5, -31, 13, 20, 6, 1, -15, 11, 16, 13, 32, 17, -32, 10, 9, 7, -37, 16, -13, -39, 6, 43, 1, 3, -39, -4, 41, -34, 16, 12, -64, -67, -4, -51, 51, 60, 12, 13, 15, -22, 4, -58, 21, 39, 35, -15, 36, 34, -7, -12, 17, -35, 45, 27, 2, 1, -2, 4, 41, 0, 39, -40, 10, 19, -1, -56, -23, 5, 41, -6, 27, -5, 18, -10, 0, -52, -28, 13, -19, -33, 7, -30, 9, -5, 2, 36, -39, 15, 8, -3, -26, 3, 33, 26, -20, 38, -16, -28, 17, -24, -35, -4, 14, 2, 23, 0, 66, 25, -8, -14, -7, 2, -16, -6, 51, 36, 10, -50, -12, -42, -52, -45, -15, -7, -14, -27, 6, 21, 19, -21, 14, 40, -12, 35, -83, -8, 2, 5, -43, -52, -28, 12, 0, -69, 8, 9, -27, 4, -49, 5, 10, -20, -40, 24, -67, 25, 17, -14, -22, 32, -5, -26, -30, 2, 20, -25, -36, 24, 29, 35, -11, 9, 8, 21, -22, -4, 11, 13, 32, -19, -10, 16, 31, 19, -4, -43, -35, -39, -17, 38, 14, 47, -15, 5, -15, 37, -3, 2, 16, -1, 33, -15, -19, 2, 21, -37, -29, 32, -35, 14, 5, 19, -25, -20, -26, -7, 3, -3, -31, -18, -29, -34, 8, 9, -11, -10, -16, -14, -24, -19, 36, 13, 12, 54, -2, 4, 4, 34, 9, -20, 34, 13, 6, -31, 29, -3, -45, -11, -28, 7, 17, 11, 3, 37, -40, 12, 23, 14, 35, 25, -35, -10, -14, -13, 4, -27, -7, -36, -26, -3, 30, -9, -28, 2, 21, 16, 8, 41, -10, 24, -3, 15, 29, -17, 40, -20, 11, -10, 1, 0, 24, 18, -32, 27, -9, -25, 6, -24, 23, -31, 5, 10, 12, 14, 20, -45, 6, 15, -48, 34, -27, -30, -2, 30, 39, 51, -21, 11, 27, -15, 15, -41, 35, -36, -45, -19, -5, -15, 27, -29, -41, -3, -11, -11, 13, 60, 6, -24, 44, 17, -27, -12, 50, 54, -9, -2, -5, 28, 12, 3, -39, -13, 23, 33, -49, 33, -12, 32, 31, 15, -18, 60, 6, -11, -6, 14, 24, 7, 28, -23, 1, 14, -25, 33, 27, 11, 4, -42, -4, -4, 29, 20, -37, 33, -18, 11, -26, -11, 21, 23, -9, -23, 3, -34, 50, -10, -7, 15, 16, -2, -16, 26, -36, 22, 14, -2, -15, -19, -10, 44, 12, 31, -18, 12, -13, -1, 21, 29, 60, 6, -11, -23, -17, -6, -25, 33, -17, -25, -40, -1, 14, -31, 10, -15, -15, 15, 37, -19, 26, -19, -11, -17, 4, 28, 38, -29, 17, 2, -24, 4, 16, -4, -4, 22, -3, 27, -30, 0, -16, 12, 31, -3, 27, 34, 32, 26, 33, 1, -26, -48, 12, 28, -42, -46, 31, 20, -22, -14, -25, -10, -22, -27, -31, 19, -13, -20, -45, -28, 29, 8, -26, -32, -35, 10, -11, -39, 10, -8, -81, -39, -7, -49, 14, -40, -41, -35, 16, -32, -16, -44, -36, 18, -7, -25, 19, 17, -53, 3, 11, 33, 10, 31, 22, -4, -32, -2, 0, -22, -52, -2, -22, 2, -14, -7, 40, -4, 44, -9, -54, -13, 17, -19, -19, -49, -50, -22, -8, -35, -42, -28, -15, -27, -28, -7, 7, -27, -59, 11, -5, 27, -22, 11, 16, -19, -27, 10, 30, -1, -31, -54, -26, -24, -3, -28, -24, -65, 10, 16, -52, -34, -37, 5, -1, 40, 27, -34, -2, 14, -31, -24, 47, -16, -31, -25, -10, 42, -44, -1, 16, -23, 3, -27, 26, 0, 5, 23, -36, 2, 24, -25, 26, -52, -48, 48, 26, -28, -11, 1, -7, 0, 34, -18, -32, 21, 17, 12, -15, 28, -1, 19, 58, 0, 15, 12, -1, -62, 39, 26, 17, 8, 18, 65, -13, -8, -15, -29, -5, -29, 16, -17, 8, 33, -14, -5, 38, 24, 25, 20, 13, 21, -22, 24, 2, -21, -8, -7, -2, -18, -11, -6, -26, 28, 24, -28, -37, 12, 43, 14, -7, 0, 22, 6, 32, 37, 16, -2, 32, 12, -2, -24, -14, -33, 34, -22, -17, 5, 15, -11, 3, 28, 12, -13, 0, 18, 24, -29, 55, 22, -19, -40, 0, -54, -42, -1, 42, -4, 7, 1, -41, 17, -31, -40, -49, -32, 21, -6, -28, -3, 19, 3, 17, 13, 13, -39, -16, 45, 33, -11, 17, -33, 20, -10, 20, -10, 27, 2, -6, -42, 32, -49, -38, -27, -30, 40, -34, -20, -27, 12, 30, 16, -7, 52, -8, 30, 28, -48, 10, -17, 23, 14, 3, -9, 16, -36, -33, 20, -26, 41, 14, 27, -22, -9, 40, -13, 24, 15, -19, -25, 49, -42, 15, -32, 34, 11, -33, 19, 22, -5, -9, 34, 17, 8, 28, 24, -31, -32, 16, -3, -14, 57, 4, -12, -48, 16, -28, 23, -15, 29, 5, -17, 6, 12, 40, -23, 22, -54, 0, 9, 4, 6, -5, -47, -32, 14, -19, 22, -48, -6, 21, 0, 55, -9, 9, 0, 48, -16, 31, 19, 33, 2, 4, -1, -16, -34, 21, 23, -30, -56, -5, -39, 16, -4, -52, -2, 38, -29, 7, -18, 0, -21, -46, 3, 0, -43, -2, 34, 7, 4, -3, -32, 27, -51, -50, -10, 13, 11, -44, -38, -4, 4, -18, 0, -26, 26, -22, 7, -48, -9, 5, 0, -14, -18, -53, 25, -31, 24, 0, -11, 24, -43, -5, -19, 2, 16, -29, -17, 15, -5, 3, -28, 58, 18, 10, -24, 63, -7, -18, -21, -40, -57, -45, 36, 33, -41, 30, -37, 9, -24, -17, 2, -1, 24, -19, -49, 13, 36, -21, 5, -52, 7, 29, -7, -13, -21, 24, -1, 33, 3, 5, -33, 17, -53, -49, 31, -51, -27, 22, -59, -20, 23, 21, 40, -28, -40, -5, 40, 34, -60, 9, -3, -28, 28, -41, 26, 5, -8, -31, -9, -37, -63, -5, 8, 5, -3, 33, -6, 7, -13, 1, 43, 40, -2, 42, -7, -15, 38, 12, 39, -20, -12, 33, 6, -33, -25, 0, -30, -13, 3, -8, 21, -22, 8, 8, -21, 24, -17, 43, -17, -21, -60, -3, 28, 21, 20, -36, 9, -8, 25, -48, -2, -12, 14, 31, 31, 28, -25, 12, 30, 8, -32, -7, 5, -15, -25, -13, -4, 15, -27, 33, -8, -13, -21, -4, 12, -21, -35, -19, -6, 33, 5, -38, -48, 39, -47, 10, 21, -23, 14, 49, -38, 39, 14, 19, 32, -28, 14, 4, -4, 3, 1, 26, -6, 8, 0, -49, -28, -7, 30, -22, 21, -5, 38, 37, -26, 7, 14, -39, -5, 6, 21, 36, -9, 25, 10, -7, -1, 13, -1, -41, 1, -5, -12, -12, -6, 24, 42, -9, 22, 18, -5, 44, -15, 4, -15, 45, 25, -8, 5, 1, -15, 33, -6, 4, -11, 23, -4, -23, -5, -11, -21, -12, 23, -41, -38, 4, -3, -31, 6, 54, 14, -20, 36, -3, -6, 2, 29, 22, 9, 17, 1, -17, 22, 38, 32, -18, -34, 42, -1, -28, 0, -16, -42, 43, -15, 39, -15, 45, -40, -16, -25, 22, 9, -22, 25, 24, -28, -15, 19, 42, 16, 2, -23, 46, 39, -17, 24, -33, 23, 3, 45, 43, -46, -15, -14, 0, 35, 2, 59, -9, -12, -35, -56, 13, 16, 33, -39, 34, 13, -13, -43, 13, -3, 30, 1, -9, 46, -37, -37, 23, 10, -31, -1, -21, 31, 23, 6, 4, -44, -21, -23, -21, -18, -51, -34, -5, 57, 45, 30, -6, 16, -38, -14, 5, -72, -48, -24, 54, -11, -3, 63, 34, 40, 9, 1, 12, -21, -5, -7, -3, 8, -1, -41, 30, 6, 4, -17, 0, -32, -68, 9, 14, 4, 5, -66, -73, -14, -5, -22, -27, 9, -3, 17, -31, -16, 39, -22, -17, -3, 2, 41, -3, 13, -36, -23, -70, 6, 4, 26, -10, 4, 3, 2, -24, -18, 28, -25, -33, -39, -22, -21, 21, -8, -29, -24, 13, 28, -2, -16, -24, 19, -2, -18, 27, -2, -29, 19, -32, -19, -4, 9, 35, 25, -1, -17, -20, 18, -3, 0, 15, 23, -44, 26, -28, -24, -17, -30, -13, 17, -10, -14, -3, -37, 12, -9, 6, -22, -30, 29, 20, -36, -13, 1, -30, -38, -40, 3, 12, 6, -35, -14, -15, -20, -21, 32, -27, -20, -28, -19, 15, 27, -34, 11, -15, -35, 24, -32, 8, -40, 7, -20, -9, 30, -7, 17, -18, -30, -38, 5, 13, -1, -11, -22, -27, -29, -34, -30, -24, 22, -15, -17, -18, -25, 10, 32, 10, -10, -2, -31, 5, 7, 15, -6, 7, 10, -37, 8, -33, -31, -22, -41, -19, 27, -32, -25, -11, 26, 5, -13, -14, -27, -24, -35, 15, 3, 26, 31, 8, -32, -12, -8, 7, -6, -41, 17, 13, 24, 4, -30, -20, 13, -33, 18, -28, 3, -12, -17, 11, 19, -22, 4, 13, 9, 14, -2, -4, -26, 33, -37, 19, 2, 20, 5, 25, 48, 8, 12, 23, -3, -26, -6, 31, -12, 13, 37, -46, 20, 49, -1, 6, -13, 28, -6, 46, -14, -22, 52, -18, 9, -29, 38, 31, -2, -23, -21, 43, 5, 6, -20, 25, 18, 3, 44, 14, -11, 34, -46, 6, -45, -5, -19, 20, 30, -20, -26, -36, 15, 38, 5, -27, 23, 7, -17, 8, -3, -12, 33, -11, -25, 26, -9, -7, 0, -37, 47, -25, -24, 28, 24, -16, -14, -27, -23, -26, 22, 7, -29, -24, 43, 6, 27, 22, -13, -1, 23, -20, -24, 22, -30, -1, 3, -40, 35, -34, 22, 19, -16, 3, 6, -10, 7, -35, -22, 6, -7, 29, -40, -40, -8, 5, -12, -31, 36, 34, 32, 4, -35, 20, -16, -1, 57, 4, -2, -7, -17, -21, 0, 47, -17, 51, 1, 25, -20, 15, 33, -17, -13, 15, -3, 8, 24, 31, 7, 43, -26, -36, 9, 25, -46, 23, -16, -7, 30, -27, -38, 40, 6, -71, 15, -20, -31, -27, 24, 48, 44, 4, -4, 17, -11, 5, -12, 16, -36, -13, 5, 2, 27, -25, -2, 7, -32, -30, -1, -32, 22, 21, -13, -9, -16, 18, -7, 0, 30, -45, -33, -11, -12, -26, 7, 30, -29, 48, 13, -23, -31, 24, -8, -25, 10, -22, 0, -6, 23, -76, 5, 25, -19, -7, -51, -14, 33, -45, 4, -37, 5, -66, -4, 10, -6, -16, -27, -59, 15, 31, 17, -34, -22, 68, 9, -1, -24, 9, 5, 15, 10, -11, -50, 22, -19, 21, -45, 11, -11, -1, 46, 31, -42, -7, -11, -4, 4, -2, 13, 34, -28, -23, -29, 7, 12, 43, 25, -6, -22, 16, -24, -11, 25, -15, 16, 13, 8, 13, 7, 15, 4, -13, -18, -17, -14, 19, 20, -24, 12, 8, -33, -29, 47, 33, -40, -9, 23, -14, 26, 14, -18, 22, 33, 29, -22, 23, 4, -14, 16, -16, 19, -26, -32, -39, -14, 20, 5, 38, -9, 8, 15, -15, 16, 14, -12, -1, 1, 18, -25, -17, -23, 35, -38, 29, 48, 34, -45, -25, -18, -35, 23, 40, -7, -13, -28, -62, -19, -13, 9, 58, -30, 0, -35, -29, 33, 6, -56, 24, 28, -3, 7, -35, -25, -44, 21, 24, -15, 30, -15, -22, -20, 11, 30, -2, -30, 34, 17, 11, -15, 29, 18, 0, 40, -17, -3, -19, 56, 11, -44, 21, 41, -33, 1, -17, 36, 6, -12, 27, -32, -9, -28, -28, -6, -25, -11, -5, 14, -22, 0, 20, -7, 18, -5, 14, 29, 14, -46, -36, 35, 12, 7, -40, 9, 15, 20, 5, 20, 18, -29, 34, -53, 28, -2, 35, 4, -28, -6, -18, 19, 20, 11, 9, -16, -30, -33, -7, 36, -23, -10, -19, 22, -13, 2, -10, 3, 11, 43, -5, -8, -52, 7, 10, 13, 4, -62, -28, 36, -5, 2, -34, -11, 19, 8, -9, 37, -34, 26, 2, 12, -56, 43, 18, -26, 13, 0, -59, -65, 14, 16, 16, -20, 28, -38, -1, -1, -10, 39, 34, 3, 34, -19, 24, -31, -38, -39, 32, 9, -32, -38, -66, -11, -25, -20, -8, -40, -14, -18, -31, -30, 1, -36, -2, -44, 42, -15, -26, 24, 35, -20, 29, 22, 23, -23, 2, 32, -36, -4, 28, -10, -15, 43, -22, -16, -33, -1, 20, 12, 13, -5, 18, 6, -9, -1, -6, -12, -25, 15, 58, 33, 18, -8, -22, 3, 38, -35, -32, -19, -39, -71, -3, 14, 41, -37, -3, 8, 23, -46, -63, -31, 5, 0, -2, -41, -27, 38, -34, 14, -25, -29, -53, -24, 16, -20, 38, -23, -18, -13, 2, 16, -10, 25, -25, 30, 25, -9, -20, -17, -1, -11, 45, 71, 9, 1, 18, -4, 33, -16, -36, 27, -9, 26, -9, -36, -9, -30, -18, -37, 21, -55, 9, -1, -51, 31, -2, -4, 16, 30, 5, 50, -4, -39, -35, -37, -7, 28, 39, -35, -11, 26, 24, 8, -21, -37, -28, -20, -39, -3, 14, 31, -5, 45, 7, -39, 39, 4, -35, -29, -20, -32, -17, -22, 20, -33, -28, -34, 35, 2, -11, -24, -24, -12, 36, 3, -39, 24, 33, 41, -29, 4, 6, 8, -15, 18, -30, 31, -42, 8, -11, -20, 25, -21, -37, 7, 11, 18, -4, -38, 3, -22, 20, 4, 33, -12, -17, 20, -36, 9, 22, 28, 6, -2, -53, 3, 14, 17, 17, -30, -36, -41, -4, -30, -9, 1, -15, 33, -28, 28, -7, 8, -26, -15, 3, 5, -55, 25, 2, 16, 27, -16, 17, -19, 28, -32, -11, -19, 18, -8, 32, 15, -59, 10, 16, 28, -5, 6, -60, -6, -15, -6, 18, 40, 20, -10, -31, -34, 17, -55, 27, 9, -54, 23, 2, -38, 4, 7, -33, 4, -19, 2, -16, 26, -29, 1, -10, -25, 10, 43, 3, -15, 2, 26, 9, 28, -20, -11, 24, 14, -3, -10, 0, -6, -7, 3, 21, -26, -7, 41, -44, 37, 24, 21, 6, -3, 21, -25, -3, 11, 46, 19, 13, 3, -29, 39, -41, 17, -28, -2, 47, 9, -5, -33, 0, 31, 2, -6, 6, -49, -35, -42, 40, 2, -18, -48, 6, 4, 36, -31, -35, -4, -18, -48, -3, -29, 5, 26, -11, -20, -7, -12, -3, 19, 15, 23, 47, -7, -9, 36, 52, -20, -33, 58, -3, 26, -26, 17, -1, -16, 18, 10, 0, 9, -2, -12, -22, 12, -34, 2, 0, -9, -17, -10, -2, 20, -18, -5, 34, -45, 14, 27, -36, -23, -21, 4, -4, 24, 28, 19, 20, 62, 32, -9, -18, -14, 2, -14, 57, 41, -6, -2, 22, -50, 43, -8, -9, 6, 2, -2, 13, -13, -24, 21, 11, -10, 17, -33, -47, -16, 32, -1, -36, -35, -30, -56, -9, -10, 17, 22, -15, 26, -18, -34, -11, -30, -29, -23, 18, -20, -12, -15, -9, 16, -56, -37, -13, 7, -23, -5, 26, 12, 7, 9, 0, -59, -5, 20, -2, 14, 58, -25, -65, -23, 39, -16, -25, 17, -42, -20, -5, 3, 20, 10, -47, -30, -15, -3, -5, -36, -22, -18, 27, -23, -49, 13, -34, 14, 36, 46, -35, 18, 8, 1, -49, 52, 29, 8, -3, 38, 8, -19, -24, 21, -28, 6, -14, -26, 11, 3, 0, -48, 14, -13, -5, 24, -20, 18, 25, 50, -24, 47, 27, 10, 14, -17, 30, 19, -4, 18, 0, 42, -17, -3, -9, -10, -28, -2, 22, 9, 1, -19, 29, -20, -58, -9, -14, 31, 15, -6, -13, -65, -13, -4, -32, 36, -15, 22, -27, 35, 45, -8, -8, -4, -13, 28, 12, -1, 44, 16, -36, -14, 41, 36, -21, -12, 47, -38, -34, -2, -33, -37, 9, -29, 29, 23, 11, 12, 24, 33, -34, 8, -7, 1, 37, 23, 17, 8, 44, -2, -9, 8, -13, -34, -7, 33, 21, 21, -25, -27, -24, 27, 23, -25, -57, -28, -12, -30, -21, 4, 0, -1, 12, -24, -22, -29, -34, 11, -11, 18, -9, -3, -37, 54, -37, 16, -16, -30, 32, 30, 1, 2, -36, -8, 20, 26, -10, 7, 2, 28, -15, 43, 7, 10, -23, -41, 7, -11, 42, 13, 30, 4, 13, -21, -3, 19, 45, 13, -5, 10, -25, -11, -11, 36, -30, -22, -21, -19, -29, 4, -27, 17, -24, -34, 41, -15, 1, 14, 37, -5, 57, 22, 8, -16, 8, -2, 4, 24, -1, -25, -6, 19, -34, 24, 11, 17, 29, -13, -24, 20, -25, 1, 78, -20, 52, 25, 6, 22, 18, 10, -35, 32, -63, 29, 25, -55, -26, -5, 4, 4, -6, 13, 25, -6, 12, -47, -9, -33, -13, -7, 33, -8, 34, -42, -12, -64, -39, 51, 11, -49, 3, 26, 33, -23, -63, 44, 18, 6, -53, 4, -1, -15, -31, -6, -39, -35, 41, -19, 11, 34, 1, 14, 2, 9, -7, 20, 15, -9, 5, -65, -18, -26, -32, 46, -30, 35, -18, -14, -14, 28, 0, 35, -18, -27, 22, -58, 46, -1, -11, -40, -48, 10, 40, 16, 34, 27, 50, 13, -45, -36, 21, -7, 24, -41, -1, 25, -17, -16, 37, -3, 18, 12, 28, -4, 10, 8, 3, 10, -53, 24, -25, -30, -9, -40, -32, -4, -14, 11, -8, 10, -23, 26, -48, -15, -29, 44, -27, -2, 12, -21, 48, 29, -22, 37, 60, -36, 6, 22, 7, 4, -48, 8, -29, 34, 40, 18, -13, 35, 33, 39, -45, -26, 15, -28, -26, 35, -50, -26, 5, -24, 11, 35, 20, -35, -7, 39, -13, -8, 6, 36, -20, 20, -5, -24, 49, -4, 7, -5, 39, -10, 15, -51, 6, 36, 10, -28, -31, -29, 38, 28, 12, -35, 42, 12, 32, -19, -15, -32, 44, -28, 1, 30, 12, 41, -16, -23, 30, 0, -26, 30, 34, 37, 10, -20, -16, -18, -27, -33, 30, 39, -8, -14, -4, 3, 25, 5, -11, -4, -33, 23, -38, -14, -17, -23, -10, 12, 15, 20, -20, 72, -3, -21, 22, 12, 32, -30, 5, 15, -18, 3, -36, -31, 26, 29, 28, 8, 12, 7, 30, 10, 12, -4, 30, -20, 21, 9, -26, 54, 7, -7, 38, -42, 17, 26, -26, 23, 17, 34, 9, 17, -11, 4, 30, 34, -30, -25, -18, -21, -7, -25, 18, 11, -5, 25, -24, -8, 23, 13, 20, -56, -22, -3, 35, 10, 20, 10, -47, 21, -2, -14, 14, -6, -4, -19, -14, -3, 41, -20, -9, 11, -13, -10, 25, 34, 3, -1, 24, 7, 26, 29, 24, 35, 21, 11, 17, -7, 38, 3, -25, 36, -16, 57, -10, -15, 16, -24, 15, 24, -32, -19, 30, -41, 21, -9, -7, -31, 11, 23, -19, -11, -35, 19, 27, -33, -8, -23, 3, -7, 14, -20, 18, 34, 26, -6, 18, -10, -4, -16, -32, -25, 17, -39, 16, -44, 21, 6, 5, 20, -15, 22, 24, 24, 3, 31, -5, -44, -48, -30, -11, 42, -28, -22, 24, -6, -31, 17, 16, -14, 24, 19, -37, 14, 4, 11, -20, 9, -36, 30, -27, 13, 0, -40, -24, -34, 25, 2, -30, 31, -30, 6, 20, -44, -28, 18, -39, 31, -18, 27, 5, 14, 5, 49, 13, -19, -25, -26, -37, 20, -27, 11, 25, -11, -27, -29, 42, 8, 1, -15, 18, 8, -7, 31, 15, -44, 22, -11, -11, 19, 28, -16, 22, 4, 41, -42, 5, 5, 31, -26, 30, 11, 0, 12, -37, 8, 36, -24, -20, 16, -38, 32, 36, 30, 33, 1, -2, -29, 46, -5, 7, -18, -11, 24, 1, -21, -15, -27, -3, 4, -55, -11, 4, 10, -2, -27, -27, -17, 23, -43, -35, -58, -23, -40, -30, 0, 34, 26, -30, -61, -43, 12, -15, 38, -15, 49, 28, 27, 3, 10, 5, -27, -17, 16, 17, -29, 55, 21, -35, 1, -24, 4, -12, 12, 46, -18, -45, -63, -43, -13, -31, -6, -17, 21, -37, 25, -17, -24, 52, -2, -59, 3, 15, 10, 10, -8, 12, 16, 54, 14, 9, -10, 25, -52, 28, 5, 28, 13, -9, -29, 11, 29, -13, 2, -15, -29, -19, -7, -5, 16, 41, -17, 23, -31, -23, 6, 4, -30, 36, -18, -6, -6, 29, -27, -26, 13, -32, -22, 37, -19, 3, 6, 8, 27, 22, -53, 19, -30, -22, 26, -5, 3, -16, 34, 39, -3, 29, -23, 6, -17, -5, 11, 2, -6, -24, 3, -26, 44, -7, 8, -28, -30, 9, -46, 40, 21, 48, -19, -6, 11, -4, 5, -21, 23, -23, 10, -25, -5, 25, -34, 4, -31, -8, -37, 36, -12, -38, -29, 21, 34, 0, -22, 22, -1, 55, 11, -36, -15, -24, -47, 17, 26, -35, -46, 9, 12, -10, 40, -47, 15, 46, 23, -29, -26, 20, -17, 13, -37, 44, -21, -43, -5, 46, 33, 0, -31, 26, 12, 43, 1, 21, -20, 8, -4, -22, -6, -26, 26, 8, -14, 15, 34, -27, 28, 8, 4, -8, 11, -22, 8, -26, 6, -37, -50, 4, 35, 9, 5, -49, -7, 5, 0, -11, -23, -9, 34, -20, -46, 13, 18, 29, -16, -33, 21, 2, 9, -27, 36, -28, -28, 43, -32, -40, 19, 30, -11, -54, -4, -33, -27, -18, -14, 0, -14, 13, 26, -26, -6, -31, -31, 23, 2, -25, -7, -20, -2, 30, -12, -31, 40, 33, -39, 8, 8, 30, -39, 22, -21, 17, 1, -3, -6, -5, -35, 20, -22, 20, -1, 2, 7, 40, 42, 28, -52, -8, -29, 33, 20, -30, -43, -5, -4, 43, -35, -23, -31, 14, -4, 25, 17, -1, 17, 9, 23, 1, 3, 34, 8, -40, -10, -1, 20, 20, -54, -15, 31, -23, 34, -41, 14, -50, 31, -3, 45, -4, -29, -1, -38, -43, 0, 21, 25, 4, 7, 22, 31, -35, 6, -20, -19, 13, 17, -33, 26, 40, 23, -8, 8, -48, -1, 6, -27, 27, 3, 32, 36, -35, -16, -22, -11, -18, 35, -11, 25, 3, -29, -40, -10, 11, -12, 5, 25, 11, 24, -37, 17, 28, 22, -8, -48, -23, -5, 28, 13, 43, 31, 2, -19, -38, 10, 9, -6, 40, 10, -1, -39, 19, 0, -21, 0, 2, 32, -43, -25, 29, -42, -7, -20, 24, 25, -26, 41, 35, -13, 44, 33, -23, -25, 29, 7, 9, 19, 18, 28, 13, 34, 27, 5, -42, 15, -3, 22, 14, -32, 28, 30, 16, -10, 36, -10, -2, 1, -48, -25, -21, 9, -10, 16, 15, 20, -8, -14, -6, -53, 11, -15, 1, -36, 26, 9, 5, -2, -21, 3, 39, -43, 10, 22, -2, 40, 36, 8, 2, -38, -1, -22, -35, -16, -34, 39, 26, 17, 0, 0, -8, 37, 1, -47, -6, 4, -28, -46, 19, -8, 30, 18, -32, 5, 12, -14, 48, 3, -30, -25, -21, 1, 20, 44, -35, -16, -11, -2, -1, -20, 7, -23, 18, -41, 35, 0, 9, 29, -21, 69, -43, 7, 6, -27, -15, 3, -30, -17, 31, 10, -16, 14, -15, 9, -18, 1, -24, -17, -13, -1, 31, 11, 24, -11, 0, -15, 14, 43, 4, 34, -35, 40, 14, 9, -3, 30, -3, -37, 43, -12, 8, -1, 28, -26, 2, -35, -21, -48, 35, 25, 27, -19, -16, -5, 10, -21, -22, -22, -2, -6, -20, -3, 1, -10, 17, 23, 6, 17, 7, -64, 19, 4, -25, 2, 36, 28, 34, -28, -8, 13, -67, -14, 3, -8, -5, 19, 21, 24, -29, -1, 13, -28, -13, -1, 14, -11, -39, 33, 41, -14, -51, 46, -33, 29, 1, 29, 29, -17, 25, 26, 28, -1, 34, 12, 34, -31, 13, 1, -3, 7, -32, 18, 24, 29, 7, 13, -11, 8, 13, -4, 26, -15, -15, 21, 17, -14, 5, -29, 8, 7, 10, 24, -18, 54, 29, 30, -39, 26, -10, 23, 29, -10, -7, 2, 38, -20, 0, -15, 16, -24, -17, -45, 21, 1, 36, 35, -33, 25, -19, -18, -24, -30, -7, -38, 15, -2, 24, 36, 0, -37, 24, -21, 23, 31, 30, -7, -18, -12, -27, -36, -1, 32, 14, -15, -14, 26, -31, -24, -14, -10, -50, 43, -34, 10, 43, 14, 13, 28, 17, 16, 25, 32, -41, -19, -35, 36, -40, 14, 23, 15, -22, 3, 13, 14, 44, 16, 56, -43, 27, 11, -2, -2, 30, 33, -59, -8, 8, 18, 20, -7, 37, 33, -36, 14, -24, -45, -13, -6, -1, -29, -30, 9, -30, 26, -14, 4, 15, 26, 30, -9, 31, 12, 4, 0, -18, 16, 36, -35, -39, 7, -20, -13, 10, 15, -5, -17, 31, -12, 1, 23, -14, 5, -19, -28, 3, 42, -4, 15, -30, 19, 49, 17, 12, 65, 10, 27, -27, 26, -22, 12, 42, -65, 15, 3, 28, -29, 31, -73, -36, 11, -46, 32, -41, 12, -1, 23, 18, -11, 52, -39, -23, -3, 5, 9, -14, -7, -32, -26, -11, 14, 34, -37, 36, 15, -5, -2, 2, -37, -26, -38, -29, 40, -4, 12, 13, -11, 9, 36, -21, 13, 39, -7, -24, -2, -44, -27, -4, 8, -15, -22, 34, -9, 5, 33, 19, 35, 6, 6, 2, -1, -15, -58, 38, -29, 43, -30, 2, 11, -4, -4, 41, -20, 2, 23, 22, -23, 0, 20, -3, 4, -26, -19, -33, 36, 11, 6, -17, 37, 8, 42, -7, 29, 27, -25, 5, 34, 12, 7, 35, 34, -22, 28, 14, -38, 20, 4, 0, -31, -4, 25, -36, 25, 24, 6, -12, 2, -10, -29, -2, 45, -5, -2, -16, -23, -22, -7, 24, -20, 28, -57, 30, -24, 15, -23, 11, -8, -9, 2, 23, -10, -42, -48, -31, -16, 26, -26, 28, -2, 27, 3, 19, 20, -49, 21, -8, 29, 12, 4, -50, 2, -2, 1, -25, -44, -23, -22, -17, -21, 4, -14, -6, 36, 20, 8, 15, -23, 1, 24, 31, -15, 22, -17, 6, -7, -25, 5, 13, -25, -3, 26, -24, 10, -29, 20, -3, 26, -7, 13, 17, 17, -22, -8, -9, 28, 9, -22, 11, -6, -40, -10, -12, 33, 36, 22, 12, 9, 25, -32, -13, -12, 37, 16, 25, -6, -6, -22, -33, 31, 16, 33, -38, 20, 13, -28, 25, -22, -24, -23, 2, -34, 11, 25, -1, -38, 24, -32, 4, -9, 23, -39, 25, 14, 26, 10, 25, -6, -5, 45, -34, -18, 21, 2, 28, -9, -24, -51, 1, 8, 20, 55, 7, 19, -56, 2, -22, 6, -41, 37, 5, -36, -14, 0, -30, -34, 35, -26, -14, 5, -53, 32, -60, -35, -12, -39, 14, -27, -6, 1, -43, 4, 17, -29, 13, -25, -35, -10, -7, 9, -14, -12, 31, -11, -51, -3, 3, 22, -9, 8, 5, 2, -14, 29, 13, -21, 24, 18, -27, -11, 26, -16, -2, 20, 37, 15, -18, 61, 5, -22, 24, 25, 32, 18, -33, 31, 38, 46, -3, 23, -22, -24, 53, 1, 34, 17, -6, 28, 18, 24, 36, -49, 20, 22, -9, 6, -12, -43, -39, -43, 53, 11, -7, 4, -20, 14, -21, -7, 7, -39, 16, 30, -3, 2, 24, -2, 51, 22, 1, -23, -27, 21, -1, 37, -40, -56, 4, 9, 3, -19, 32, -2, -28, -6, -8, 9, 2, -32, -72, 11, 0, -45, 20, 25, -54, -25, 53, 6, 15, -51, 8, -40, -68, 3, -8, 12, 33, -36, -10, -84, 12, -39, -2, 5, -26, -30, -43, 1, 14, -17, 18, 44, 58, -21, 32, 19, 41, -73, -30, 29, -29, -20, 26, -9, -29, 32, -11, -34, 16, 46, -20, -10, -25, 51, 27, -40, 14, 28, -13, 3, -28, -17, -24, -66, 10, -4, 2, 0, 27, -19, -26, 4, -29, -32, 4, -12, -27, 23, 28, -1, -21, -31, 63, -24, -21, 13, 54, -9, 15, -43, 25, -29, 37, 12, -6, -15, -11, -22, -25, 20, 0, -21, 35, 19, 22, -22, -18, -14, 1, 25, 27, 22, 14, -34, 13, -7, -52, 10, 8, -8, 15, -18, 14, -21, -30, 39, 62, -1, -20, 42, 9, -4, -22, 19, -3, 5, 15, 7, 3, -42, 26, -39, -40, 0, -29, 9, -48, 39, -19, -4, 24, -25, -36, -35, -19, 32, -8, 38, 23, -3, 11, -14, -23, 48, -7, -35, 1, -30, -10, -26, 19, -19, -1, -3, 8, -37, 23, 24, -11, -15, -39, -17, -15, -61, -29, 22, -62, 19, 23, 43, -7, 12, -14, 37, -1, -17, -19, -18, -10, 18, -16, -28, -61, -20, -35, 23, 17, 20, -4, -75, -28, -31, 8, 26, -28, -4, -11, -18, -13, -13, 10, -44, 1, -66, -6, 0, -5, 51, -11, -40, 10, 7, 8, 7, -33, 38, -6, -2, 20, 17, 7, 16, 35, -22, -18, -6, 11, 23, 21, -21, -19, 20, 38, -2, 5, 10, -38, -25, 4, 17, 9, -34, -20, -12, 14, 40, -19, -28, -12, -9, -31, 20, -21, -26, -9, -10, 34, 21, -10, -8, -39, 34, -41, 0, 26, -2, -14, -5, 0, 33, 10, 3, 12, -55, -2, -5, 6, 12, 37, -12, 35, 7, -27, 8, -16, 39, 25, 13, -14, 3, 27, 24, 16, 10, 38, 24, -6, -6, -8, -44, 0, -6, -21, -22, 30, 49, 19, -31, 8, -22, 0, 31, 25, 41, -9, 26, 38, -46, -29, 6, -26, 28, 22, -3, -25, -27, -4, -26, 19, 9, -41, 0, -29, 28, 13, -27, 21, -30, -33, -13, 13, 11, 31, -19, -33, -13, 25, 5, -31, -1, 11, 25, -4, 8, 6, -19, 11, 1, 38, 20, -39, -28, 33, -8, -36, 29, 17, -2, 10, 50, 40, -8, -49, -20, 54, -7, 4, -23, -32, -8, 18, -17, 15, 12, 1, -6, -2, 12, -24, 20, 35, -11, 8, -30, -18, -8, -11, 1, 7, -22, 31, -23, -13, -16, -42, -26, 9, -22, -22, 17, -6, -7, -38, -25, 13, 33, 3, -10, 51, 5, -16, -1, 39, -22, -7, 16, 19, 14, -41, 19, -84, -2, -46, -28, -18, 1, -52, -22, 8, 15, 8, -2, 12, -5, 19, -14, 36, 28, -9, -22, 0, 48, 15, 26, -14, -15, 13, 31, -3, 34, -34, 35, -22, 15, 31, 29, -26, -12, 33, 1, -21, 29, -21, -2, -18, -27, -11, -10, -4, -10, 0, 9, 2, 29, 16, 8, -39, -32, 43, 38, -10, -6, -22, 13, -32, 14, -9, -14, -29, 13, -39, -6, -11, -51, 0, -30, -35, -30, 9, 6, -6, -27, 32, -10, 14, 1, 1, -16, -39, -6, 30, -37, 9, 34, 7, 4, 30, -14, 3, 21, 23, -8, 23, -19, -14, 49, -22, 31, -17, -17, 11, 40, -19, -13, 4, 37, -6, 20, 2, -28, 44, 0, -24, 18, -10, 34, 52, 42, -14, 9, 9, -21, -36, -25, 41, -12, -28, -32, -33, -9, 8, 15, 11, -45, 39, 25, -9, 9, -4, -4, -5, 17, 4, 3, -25, -4, 49, 52, -19, -6, 34, -8, 5, 5, -25, -22, -17, 14, 2, -53, -17, 24, 4, 28, -15, 43, 25, -7, 3, 37, 28, 27, -2, -24, -18, -25, 5, 24, -1, 2, 26, 19, -6, -32, -15, -35, 2, 53, -2, 36, 29, 30, 14, 38, 13, -24, -27, 32, 38, 5, -26, -27, 24, 4, -52, -33, 11, 21, -2, -11, -15, 20, 14, 3, 61, -32, -14, 9, -32, 4, 38, -23, -43, -20, -14, 21, 27, 21, -43, -10, -25, -25, -11, -3, 15, 11, -33, 2, -18, 41, 32, 30, 7, 53, -3, 43, 2, 9, -10, -3, -35, 1, -23, 39, -7, -17, -31, -13, -27, 34, 40, 10, 12, 24, 55, 15, -30, 4, -40, 19, -25, -23, -4, 4, 23, 23, 27, 13, 45, -14, 31, 4, 20, -32, 37, -16, -8, 19, 1, -21, 17, 5, 50, -32, 16, -8, -20, -35, -28, 14, 44, -3, 0, -37, 31, 18, -15, 22, -14, -21, 13, 1, 29, 39, 53, -23, -27, 24, -32, -32, -10, -24, -13, 18, 32, 16, 21, 17, 1, -49, -32, 20, 39, -6, 16, 46, -34, -8, 8, 16, 24, 12, 22, 56, -13, 34, -14, -6, -46, -19, -13, 7, 25, -25, -58, 24, 14, 6, 25, 32, 29, -25, 0, 16, -9, -51, -46, -17, 21, 6, 12, -6, 18, 14, 35, -45, -22, 15, -7, 69, -12, -9, -26, -70, 3, -10, 16, -14, 17, 16, 14, -20, 6, 9, 24, -11, -26, 18, -6, -25, -6, 2, 28, -44, -60, 14, -8, 15, -45, -16, -28, -7, 31, 5, 0, 41, 59, -5, -42, -19, -1, -34, -14, -4, -23, 45, -31, 5, -26, -15, 6, 27, -6, -51, 10, -7, -20, 19, 2, 6, -17, 10, 57, -50, 11, -10, 8, 12, 4, 17, 21, 17, 15, 1, 45, 22, -18, 10, -61, 29, -17, -56, 8, -53, 11, 7, 44, -10, -52, 12, -57, 16, 9, 4, 12, 29, 1, -1, 11, -24, 40, 25, 24, -56, -44, 59, -22, -18, 9, -23, -56, 19, 4, -36, -41, 25, -75, -17, -87, 14, -35, -57, -27, 4, -37, -6, 25, -28, 12, -25, 14, 13, 32, 13, -13, -25, -36, -67, 20, 22, -8, 49, -41, 6, 1, 19, 17, -18, 20, -3, 15, 12, -4, -10, 29, -14, 6, -10, -4, -28, -3, -11, -51, -19, 34, 19, 7, 3, -27, 0, -50, -25, 10, 31, 19, -8, 6, -5, -29, -22, 12, -14, -33, 22, 14, 38, -37, 2, -49, 3, -27, -24, -31, 54, -58, 28, 0, 1, -28, 7, 26, -12, -14, 25, 31, 29, 22, 25, -14, -8, -44, -17, 22, -13, -46, -37, 2, -23, -10, 22, 13, 17, -11, 38, -33, -17, -27, -81, -19, -40, -34, 44, -28, 61, 26, -36, -35, 39, 13, 12, -17, 20, -36, 30, -40, -10, -7, 7, -9, 8, 35, 10, -55, -21, -8, -7, 29, 27, -31, -22, 1, -18, 7, 7, -37, 5, 23, -15, -45, -27, 47, -21, 32, 9, -21, -12, -4, -3, -6, -30, -32, 2, -35, -1, 23, -44, 8, 15, -4, -5, 23, 11, -19, 39, 53, -2, 31, 2, -57, -26, 4, -8, -11, 18, -17, 19, -17, -1, 13, 23, 8, -30, -53, 7, 4, 11, 2, -15, 32, -66, -49, -41, 14, 7, -53, -27, -44, 40, -41, 39, -28, 11, 19, -2, -30, -30, 11, -4, 5, 11, -20, 9, 34, 2, 15, 55, 26, 26, -14, 20, 20, -8, -23, -20, -29, -7, -38, 9, -1, 0, -7, 7, -44, 32, -3, 4, 28, -13, -17, -25, 11, -52, -41, -17, -26, -50, 31, -14, -13, -6, 61, 0, 24, -49, 25, -23, 23, -37, -23, 1, -6, 9, 24, 35, -12, -5, -24, -1, -26, 5, -10, 24, 15, -13, 12, -40, 17, 23, -21, 1, -39, -8, -15, 0, 42, 28, 16, -20, -34, 32, 23, 15, -40, 35, -26, 84, 28, -45, 29, 11, -22, -22, -33, -20, 2, 12, -2, -42, 24, -15, -13, 2, -27, -6, 40, 37, 28, 19, -6, -35, -56, -25, -39, 47, 19, 33, 25, 39, 10, -37, 3, 14, -13, -11, -2, -30, -47, -1, 12, -17, 8, -32, 25, -7, 13, 34, 32, 17, -7, 3, 37, -9, 40, -42, 5, -15, 8, -29, -34, -44, 24, 44, -6, -1, -14, -24, -30, 0, -17, -51, 34, 14, 23, 12, 35, -17, 19, 34, 7, -14, -35, -23, 8, -20, 8, -10, -10, -1, 57, -4, -20, 29, 32, -52, 22, -21, 30, 26, 4, -29, -51, -42, -5, 39, 8, 15, 34, 14, -1, -19, 57, 3, 47, -37, -73, -15, 40, -18, -40, -25, 16, 19, 17, 36, -24, -21, 17, -2, 27, -32, 8, 15, 25, 17, 0, -34, 8, 18, -34, 14, 18, -22, 43, 38, 11, 3, -9, 35, -10, -10, 30, 27, 22, -32, 19, -71, 27, 43, 27, -30, -55, 13, -49, 14, -23, 47, 54, 33, -4, 35, 10, -63, 10, -46, 16, 49, -64, 41, -51, -10, -5, -25, -11, 25, 3, -35, -38, 45, 28, 22, 4, -21, -13, -24, 31, 19, 14, -4, -20, -65, -27, 14, -58, 16, 25, 23, -32, 23, -15, -13, -6, -48, -44, -27, -10, -24, -22, -17, 12, -24, 15, 15, 2, 22, -12, 52, -30, 28, 39, 2, 19, -31, -2, -36, 31, -40, 7, -19, -81, 11, -29, 31, 2, 25, -17, -29, 35, 18, -39, -5, -17, 4, -23, 7, -1, -26, 27, 17, 60, -18, 2, -14, -14, -8, -16, 43, -19, -12, 0, 31, -56, -46, -16, 47, -4, -35, 37, -23, 16, 19, 14, 39, -13, 16, 23, -29, -51, -5, -2, -1, 34, -40, -62, 27, -34, -6, -18, 15, 27, 21, -39, -6, 11, 28, -10, 45, 1, 20, 40, 4, 16, 35, 17, -18, 11, 12, 6, -32, 26, -4, -57, -39, 12, 17, -24, -16, -44, 14, -21, 30, 20, 21, 10, -5, 22, 33, 38, 13, -17, -19, -11, -23, -25, 4, 31, 25, 38, 4, 8, 16, 26, -6, -10, 17, -3, 35, -32, 20, 12, -1, 10, -43, -29, 11, 12, -28, 15, -9, 8, -42, 42, -21, 48, 8, -19, 20, -7, -12, 25, -18, -44, -10, 0, -17, 36, 41, -11, 31, -54, 4, -9, -23, 28, -28, -8, -8, -8, -37, 0, -34, -19, 3, -61, -22, 6, 27, 1, -33, 8, -33, 12, -8, 17, 3, -10, -20, 36, -15, -12, -32, -16, -10, 5, 25, -31, 50, -2, -12, -1, -1, 25, -29, 4, 6, -38, 16, 1, -21, -26, -65, 10, -22, 7, 0, 8, 37, 48, -24, -12, -1, 22, 2, 20, -19, -51, -11, 6, 42, 40, 39, -20, 1, 8, 19, -23, -23, 15, 29, 19, 7, -17, -29, 5, -15, 24, -35, -49, -3, 27, -27, -3, 0, 52, 8, -24, -36, 29, 6, 44, -50, 11, -13, -17, 14, -19, 7, 24, -25, 29, 26, 17, -42, 32, -24, 27, -25, -19, -37, 29, 9, 14, -3, -65, -13, -25, -30, -1, -1, -3, 38, -20, 41, 27, 42, 8, 0, -17, -19, 16, 10, 30, -3, -40, -2, -56, -20, 52, 11, 9, -39, 16, -6, 5, -18, -21, 9, -48, 32, 53, 5, 8, -25, -9, 33, -18, -31, -13, -67, 36, 28, -37, 5, -17, -14, 8, 0, -2, 6, 9, -26, -14, -22, 23, 23, -6, 1, 15, -5, 34, 3, -21, -17, 34, 29, 26, 0, -48, -21, -29, -12, 3, 47, -24, -2, -7, -34, -16, 52, 65, -62, -7, -38, 30, -44, -12, -7, 4, 12, -10, 42, -15, -48, -38, -28, 24, 42, -49, 2, 7, 34, -29, 12, -5, 12, -48, -40, -30, 14, 8, -11, 18, -34, -25, 40, -29, 9, 51, 36, -15, -7, 8, 45, 21, 4, 8, -35, -21, -16, 6, 29, -30, 0, 3, 1, 12, -8, 32, 18, -31, 27, 80, 1, -80, -33, -17, -58, 5, -14, 0, -43, -37, -20, 46, 36, 54, 18, 25, 20, 33, 6, -4, -16, -9, -16, -40, 0, 20, 21, -61, 43, 6, -12, -26, -30, 20, -24, -33, 19, 22, 12, 46, 23, -1, -75, -25, -11, 32, -22, -23, -39, 40, 62, -18, 10, -35, -47, 38, 36, 42, 15, 22, 9, -2, 13, 22, 33, -7, -24, 24, 32, -3, -11, 33, 5, -7, -28, 39, -36, 16, -17, 10, 27, -39, 2, 59, 2, 41, -17, 34, 1, -29, -34, -3, 23, -65, 2, 13, -44, 18, -51, -20, -22, -24, -33, 28, -29, -5, 22, -1, -14, 17, 1, -32, 56, 18, 18, 48, 17, -32, 47, 19, -47, -29, -2, 11, -5, 33, 2, 7, -31, 12, 4, -2, 12, -21, -7, 18, -11, 21, -19, -47, -42, -32, -33, -34, -10, -18, -17, 19, -35, 39, -44, 8, -22, -9, 20, -20, -24, 11, -38, -26, -22, 8, -37, -9, -5, 11, -28, -8, -32, -64, -11, 14, 3, -28, 28, 15, -15, 13, -13, 1, -20, 17, -5, -39, -23, -16, -25, 14, -36, 40, -40, 17, 32, 19, 10, -30, 1, -28, -33, -2, -3, -14, -25, -13, -5, -1, -62, -25, -56, 8, 19, -30, -19, -42, 17, -40, 14, 18, 16, 15, -26, -35, -4, -43, 52, 1, -11, 0, -13, -41, 23, -28, 34, -9, -41, 29, -32, -3, 12, -21, -13, -33, 22, -17, -20, 0, -27, -30, 22, -30, -13, -18, 43, 6, 4, 27, -1, 34, 6, 1, -18, 22, 35, 53, -36, -2, 3, 25, 16, 2, -20, 9, -3, 49, -12, 57, 11, -53, 53, 37, 6, 17, 25, -20, -16, 44, -22, 22, -25, 3, 11, -11, -42, -60, 26, -33, -56, 13, 13, -26, -21, -26, 7, -21, -11, 16, 13, 14, -55, 48, -36, 35, -37, -27, -28, -7, 54, -7, 15, -4, -18, 20, -7, -25, -5, 39, -14, -55, 7, -19, 52, 30, -28, -17, 16, -4, -21, -35, -15, 1, -5, 17, 3, -29, 53, 30, -14, -23, -32, -6, -13, 32, 1, 9, 24, 2, -35, 0, -8, 24, 1, -3, 45, 12, 3, 42, -9, -11, -23, 45, -45, -32, -2, -4, 0, -13, 30, 16, 17, 54, 33, 37, 15, -3, 0, 33, 47, -12, 6, -6, 38, 11, -25, -29, -39, -25, 24, -22, 27, 28, -19, 33, 20, 20, 23, 6, 41, -1, -12, -8, -30, 5, -11, 8, -15, 32, -62, 13, -42, 12, 23, -15, -36, 25, 47, -1, -5, -22, -9, -39, -2, 57, -3, 37, -38, 21, -13, -35, -24, -65, -25, 26, 23, -59, -6, 25, 0, -4, -5, -37, -8, -15, 5, 23, 2, 15, 13, 7, 15, -6, -19, 46, -4, 20, -7, -1, 27, 23, 3, -21, -6, 24, 4, -26, 16, 35, -8, 31, -16, 2, 20, -9, 4, -1, -29, -46, 32, -30, 40, -10, -30, -9, 1, 27, -40, 23, -6, 31, 5, -18, 7, -13, 0, 19, 14, 6, -20, 13, 33, -23, -20, 49, -24, 27, 38, -20, -33, -12, 3, 23, -10, 0, -29, -9, -18, -25, 24, 28, -7, -16, 29, -47, 5, -44, -5, 12, 12, -28, 63, 22, -37, 31, 23, 32, 30, -14, -34, -51, -41, 13, 32, -1, 27, 19, -1, 34, -3, -17, 7, -7, 26, 24, 23, -4, 38, -37, -21, 26, 12, -36, 6, 3, 18, 15, -18, 11, -57, 38, -15, 11, 4, 5, -7, 38, 26, -2, -32, -27, -6, 37, 27, -10, -12, 1, 1, 28, 5, -31, 4, 26, -16, -31, -15, 34, -20, -14, -13, 23, -16, -52, -18, 29, -27, -12, 5, 10, -57, -22, 12, -8, -18, -44, -40, -16, 19, 19, 51, 1, 22, -35, -1, 8, 50, -36, 8, 13, 26, -35, -25, 48, -9, 32, 10, 44, -45, -20, 11, 19, -11, -4, 10, -32, 17, 42, -13, -30, -3, 53, -12, -34, 34, -43, 2, -34, -8, -29, 14, 67, 39, -20, 6, -24, -34, -4, 58, -9, 41, 31, 48, -32, 3, 8, 25, 6, -20, -3, 47, 26, -38, -8, -46, 39, -43, -20, 27, 0, -7, 4, -16, 5, -19, -36, -19, -4, -20, -16, 7, -34, 15, 31, 1, 30, 0, -27, 5, -14, -9, 1, -22, 21, -3, -30, -11, 13, -22, 13, -25, -49, -2, 3, -23, -13, -17, 15, 4, 13, -39, 27, 16, -18, -30, 19, -4, 8, 40, 34, -27, -42, -51, -5, 30, 6, 24, 24, -51, 21, -13, 31, 26, -47, 52, -2, 18, 15, -75, -56, -49, 27, -2, -22, 6, -30, -2, 18, -9, -19, -38, 22, -14, -6, -10, 25, 29, 6, 36, -50, -9, 10, -49, 13, 25, -26, -26, -53, 17, 20, -19, 16, 28, -3, 26, 19, 46, 8, -9, -85, -36, -40, 12, -36, 23, 21, 13, -21, -31, 5, 7, -24, -58, 2, 18, 2, 2, -44, -53, -6, -22, -13, -8, 53, 4, 13, 10, -25, -41, -36, -21, 30, -30, 48, 10, -17, 44, -2, -12, -18, -20, -39, -29, -17, 7, -29, 11, -52, 4, -17, 46, 16, -17, 41, -8, -34, 6, 34, -2, -40, 15, 17, -11, -56, 20, -28, -9, -12, 20, -47, -35, -29, -27, 40, -42, -25, -1, -8, 24, 33, -9, -12, 32, 1, 0, 21, 22, -55, -22, -28, -38, 56, 25, -14, -1, -9, -42, -40, 23, 29, 17, 9, 11, 28, -4, -3, -4, -20, -14, 12, -9, -44, -37, -6, -21, 41, 29, 1, -27, 8, 0, -23, 8, -8, 6, 32, -4, -34, -41, -16, 16, 28, -31, -31, 54, 44, 2, -4, -27, 29, -3, -18, 45, 33, -75, -39, -9, -58, 9, -57, 19, -5, -28, -11, 19, 38, -40, 31, 12, 16, -21, -1, -17, 22, 19, 0, 16, -23, 2, -17, -28, 17, 16, -16, 29, -3, -7, -11, -5, -42, -17, 16, 25, -2, -17, 11, -35, 4, -51, -40, -2, -19, 22, -20, -16, -21, 40, -7, 2, -22, -6, 14, -15, 16, -40, 18, 9, -39, 1, -11, -44, -25, -16, -21, 28, -11, -34, -10, -11, -30, -24, -27, -7, 8, 19, 42, -9, 53, -34, -1, -7, -43, -36, -23, 7, -16, -44, 12, 37, -20, 17, 31, -9, 35, 8, -5, -76, 43, -9, -17, -18, 6, -33, -18, -19, 20, -36, -20, 22, 19, -10, -11, 16, 18, 2, 5, 14, -29, 13, 39, 13, 14, 11, 14, 20, 22, -17, -17, 23, 0, 23, -44, -18, 53, -36, 12, 5, 4, -36, 22, 40, -52, -12, -2, -31, -6, -27, -8, 25, -50, -33, 27, -44, -49, -22, -5, 36, 17, 9, 14, -24, -34, 4, 32, -17, 22, 41, 13, -9, -23, 3, 3, -22, -32, -33, -6, -25, 24, 29, 27, 16, -6, -21, -26, 21, -35, -9, 3, 50, 36, 20, -33, 8, 10, -17, 33, -27, -7, 7, 1, 17, -26, 22, -9, -4, 39, 33, 10, -10, -7, -30, -61, 27, -39, 18, 0, -2, -31, 34, -15, -3, -61, 10, 17, 13, 4, 30, 2, -30, 27, 12, 11, 45, 13, -29, -39, 34, 48, -42, 22, 29, 23, 41, -1, -24, 1, -28, 4, 22, 21, -8, 56, 29, 10, -24, -3, 29, 10, -22, 28, -22, 12, -8, -20, -15, 21, -41, 29, -46, 41, -6, -4, 2, 17, -21, 16, 25, -9, 7, -13, 61, -28, 35, 37, 37, -51, 17, -25, -26, 16, -34, 13, 27, 4, -39, -20, -15, -31, -43, -13, -7, -17, -30, -7, 38, -2, -48, 46, 26, -1, -19, 56, 53, -38, -14, -19, 27, 30, -47, 10, -4, -3, 51, -37, -25, -43, 25, -6, 24, -37, 6, -8, 31, 36, 8, -40, 19, 3, -19, 44, 21, -14, -1, 18, -43, -36, 10, 6, 30, -57, -4, -22, 4, -12, 31, -50, -2, -12, 8, -5, -8, 10, -9, -15, -42, -15, -27, 13, -4, -5, -2, -8, -43, 21, 2, 5, 36, 8, -23, 0, 12, 34, 26, 1, -2, 0, -44, 0, -48, 16, 12, 9, 41, 13, 10, -28, -42, 15, -30, 30, 26, 16, -47, -41, -57, 40, -37, -6, -3, -16, 12, -23, -32, 28, -8, -6, -17, -10, 6, -5, -32, -13, 19, 36, 29, -38, 23, 36, -3, -16, 5, 40, -2, 11, -6, -13, 3, 18, -10, 3, -33, -28, 6, 15, 43, 24, -38, -20, -2, -29, 17, 37, 47, -30, -20, 7, 54, 37, 28, 7, -5, -8, 25, 39, -48, -24, 5, -21, -9, -21, 15, 3, 10, 14, -14, 27, -25, 15, -10, -17, -21, 28, -16, -23, -16, -5, 5, -23, -1, -22, 3, -21, -15, -3, 31, -25, -8, 29, 43, 33, 12, -16, -20, -12, -18, -51, 28, 41, 45, -5, 2, 39, -27, -18, 9, 12, 35, 23, 37, 9, 20, 31, -28, 12, -8, -2, 31, -60, 42, 25, -38, -3, 4, 13, -32, 40, 27, 35, -25, 21, -9, 15, 4, -17, -20, 25, -32, -57, -19, 17, 2, -36, -49, 26, -22, 15, -45, -19, -42, 40, -27, 0, -7, 19, -10, -15, 17, -58, 1, -30, 19, 19, 16, -24, 0, -15, -30, 41, 21, -23, -11, 4, 26, 18, 21, -13, -27, -28, -28, -11, -37, 33, -14, 16, 8, 19, 26, 46, -32, -14, -2, -25, -17, -38, 30, -11, -40, 1, 0, -40, 8, 24, -18, -3, -15, 2, 10, -10, -8, 6, 34, 22, -34, -30, -7, 4, 12, -17, 13, 25, 1, 12, -3, -19, -42, -8, 11, -9, -9, 17, 5, -19, 41, 34, -31, -26, 28, 30, -24, -27, 12, -13, -8, -25, -5, -45, -2, 31, -33, -2, -8, -78, -26, 3, 20, 28, -42, 21, -19, 3, -19, -16, -11, -37, -29, -58, 19, 38, 7, -57, -40, -41, 19, -32, 37, 36, -3, -2, 30, -46, 17, 57, -51, 10, 8, -25, -20, -3, -10, -1, -24, 26, -10, 10, 21, -13, 41, -20, -19, 51, -7, 35, 29, -7, 14, -58, 34, 58, 44, 13, 30, -12, 13, 16, 26, 7, 9, 20, -23, -8, -24, -1, -9, -2, -37, 10, 16, 45, -20, -11, 5, 37, 16, 7, 8, 0, 15, -4, -13, 18, 2, 16, 12, -19, 11, 13, -19, -23, 18, -6, 14, -36, -29, -41, 25, -20, -8, -39, 48, 0, -26, -40, -38, 1, -8, 65, 27, -17, 5, -13, 3, 12, -33, 21, 27, 32, -24, -5, 26, -16, -25, -27, -9, -2, -3, -51, 27, -47, -2, -15, -31, -35, 39, -39, 4, 6, 10, 2, -23, 31, -43, 5, 9, -30, -74, -52, -58, -16, -29, 11, 7, -47, 12, -25, 28, 28, 8, -18, -33, 30, 26, 16, -11, 12, 1, 28, -5, -59, 60, -19, -23, -14, 7, 17, -50, 0, 28, -1, 22, 39, 0, -1, -3, 17, -10, -19, 29, 10, -31, 16, -5, -30, 30, 59, 39, 13, -3, -33, -18, 42, 44, 7, 24, -23, 14, -11, -26, -18, -39, -34, 31, 13, 20, 38, 0, 53, 2, -22, 4, 14, -33, 1, -41, 8, -36, -54, 0, 27, -42, -10, -37, 44, -5, 29, 21, 45, -20, 40, -30, 0, 26, 3, -37, -8, 29, 19, 30, -18, 1, 9, 18, -4, -9, 29, 44, 33, 12, 25, -23, 2, 37, 27, 0, -33, -21, 13, -39, -27, 50, 43, -21, 16, 31, -8, -36, 67, 0, 20, 31, 30, 20, -29, -6, 20, -18, -31, -6, -28, -28, -37, 22, -55, -14, 14, 9, 18, -4, -15, 13, -34, 17, -10, 16, 12, -9, -22, 13, 16, 20, 26, 24, 29, 2, 26, 26, 44, 12, -42, 10, 22, 17, -4, -11, -16, 25, -39, 1, -13, -23, 30, 4, -11, 22, 2, 11, -36, 38, -33, 36, 30, 8, -23, 22, 27, 49, -23, 5, -34, 53, 32, -14, 28, -31, -36, 11, -4, 2, -11, -18, -7, 5, -23, 41, -34, -15, 3, 27, -9, -27, 4, -12, 0, -45, 1, -19, -7, -18, 10, -21, -35, -4, -18, 57, -44, -65, -24, -9, 18, 26, -13, 18, -11, 25, -25, -4, 8, -29, -26, 39, 25, 18, 8, -77, 10, 30, 5, 11, 20, 7, -18, -6, -24, -10, -20, -10, 10, -4, 15, 22, 47, 10, 5, -9, -92, 4, 33, -27, -15, -31, -7, -38, -33, 28, 46, 17, 34, 28, 3, 23, -33, -34, -4, 31, -11, 24, 4, 61, 20, 13, 31, -42, -34, 40, 8, 17, 24, -11, -8, -28, 8, -14, -7, 24, -1, 22, 16, 15, -44, 19, 5, -4, 23, -27, -14, -32, 12, -4, 26, 16, -5, 39, -31, -3, -30, -4, 20, -14, 4, 35, 39, -3, 29, 29, -13, 12, 34, 30, 26, 15, 44, -29, -1, -22, -20, 2, -1, 6, -17, 35, -12, -2, -16, 48, 8, 7, -38, -33, -23, 3, -12, -21, -34, -7, -13, -35, -3, 24, 2, 7, -2, -8, -11, -26, 24, 5, 28, 37, -11, 46, 27, -31, -35, -19, 54, 11, 12, 5, 21, 2, 25, -11, -9, 14, -6, -31, 17, -29, 29, 10, -34, -33, -2, -26, -43, -9, 16, -22, 6, -49, -21, -52, 5, 35, 25, -47, 26, 21, 28, -15, -15, 11, 12, 33, -31, -1, 23, -28, -8, -1, -24, 38, 22, -8, -18, -50, 37, 46, 31, -41, 23, -50, 5, 8, 39, -26, 44, 8, 22, -30, 13, -19, -24, 31, 20, 2, -6, 18, -14, -16, 14, -20, -2, -25, 17, 1, 0, -35, -34, 36, -6, -10, -43, 17, -2, 31, -25, 3, 42, 14, 9, 2, 25, -9, 29, -9, 44, -22, 28, -46, -33, -2, 13, -22, 5, 22, 15, -4, -1, 38, 1, -8, 17, 69, 15, -11, 56, 39, 9, -25, 6, 1, -17, -21, 6, 23, -55, 13, 16, -13, 1, 3, -8, -10, 25, -31, -11, 9, 9, 10, -35, 52, -15, 30, 24, 8, -28, 22, 30, 60, -10, 5, -25, -29, -18, 31, 11, -24, 7, 40, 7, -21, -30, 4, 17, 20, 18, 33, 21, 34, -20, -24, -62, -33, 8, 4, 22, 40, 20, -2, 8, 3, -12, -27, 9, 34, -5, 36, -36, -19, 1, 0, 6, -5, 29, -5, 17, 28, -11, -22, -9, -21, -1, 42, 25, 37, -10, -11, -57, 22, 39, 16, 29, -46, -58, -6, -13, 28, 29, 9, 21, 31, -33, 25, 47, -37, 42, 39, 51, -17, -13, 42, -1, -18, 17, -1, -5, -8, 12, 39, -10, 19, -6, -26, -50, 37, 26, -16, -7, -40, 22, -18, -31, -1, 3, -39, -8, 52, 48, -42, 29, -9, -18, -13, -11, 2, 15, 11, 6, 20, -4, -26, -15, 5, -38, 3, -60, 23, -22, -20, 34, -19, 10, 38, 23, 51, 3, 17, -7, 23, -34, 9, -33, 38, -36, -47, 6, 32, -56, -4, -2, -1, 25, 17, -37, -6, -28, -36, -28, 44, 16, 38, -4, 34, 16, -33, -34, -2, -24, 26, -18, -4, 36, -2, -36, -68, -15, -57, -4, 37, 12, -30, -25, 6, -20, -7, -14, 0, -29, -52, -16, -56, -43, -28, 5, -16, -62, -36, 22, -35, -42, 32, -17, 62, 42, -8, -60, -14, -18, -43, 6, -35, -36, -34, -3, 1, -3, 10, -8, 23, -28, -42, 25, 43, -26, 8, -24, -67, 26, 0, -40, 33, 15, 2, 38, 21, 17, 13, -26, 23, -36, -6, -35, 1, 14, -15, -14, 12, 12, 42, -65, -36, -49, -33, -21, -21, 29, -51, 18, -5, -29, -1, -53, -7, 43, 10, 35, -19, 10, 18, -40, -27, -44, -8, -10, -36, 16, -4, -8, -19, 13, 22, 11, -50, -86, -4, 28, 18, 20, -8, 34, -28, 31, -17, 42, -18, 26, 40, 27, 15, -20, 0, -36, -4, -33, 37, -2, -51, 15, -30, -14, -29, 10, -24, 36, -23, -18, -4, 17, -45, -8, 28, 41, -12, 50, 25, -49, -17, 29, -33, 12, -20, 25, 0, -9, 12, 26, 30, 34, -26, -1, -38, -5, 26, -24, -8, 15, 1, 48, 5, -4, 0, -50, -10, 35, -17, 52, 29, -44, 43, -1, -6, 33, 31, -18, -1, 30, -24, -16, 33, 25, 28, 0, -23, -44, 14, -27, 27, 20, 3, 30, -31, 24, -43, -3, -22, -4, -4, 19, 35, -29, -66, 23, -16, -5, 32, 29, -16, -35, -14, 25, -19, -11, 1, -13, -30, -28, 37, -30, 17, 4, -22, 53, -29, -30, 22, 0, -35, -29, 21, -31, 11, -34, -11, 23, 6, -45, -24, 25, -21, -20, 13, -31, 13, -5, 25, 16, -32, 56, 11, -6, -43, -4, -30, -64, 12, -5, 11, -30, -2, 13, 4, -10, 5, 10, -92, -14, 25, -20, -5, -14, -2, -39, 40, 11, 32, -9, 23, -21, -17, -36, 15, -44, -20, 14, 11, 52, 24, -2, -35, 44, -35, -32, -20, 15, 21, 42, 3, 9, -13, 39, -24, -32, 3, -6, 24, -8, -38, 29, 3, 50, -3, 27, 28, 21, 33, -3, -1, -15, 29, 9, -17, -29, 21, 11, 5, -3, -75, -24, -10, -11, 21, -16, 36, 40, -20, -11, -33, 13, -16, 4, 22, 2, -11, -47, 61, -10, -52, 38, -20, -15, 2, -3, -24, 14, -44, -31, -44, 1, -14, -5, -39, 6, -22, 34, -8, -23, -41, -48, 24, 3, 0, 19, 15, -19, -4, -6, 32, 8, 29, -32, -22, 12, -38, 7, -5, 4, 40, -39, 4, 12, -42, 11, 20, -10, 7, -11, -19, 40, -3, -32, -43, -22, 33, 36, -10, -43, 8, 41, 0, 18, 29, -2, -18, -38, -10, 31, -43, 24, -39, 33, 22, -19, 17, -23, 29, 32, 30, -5, -4, -37, -2, 21, 8, -26, 10, -43, 13, -18, 2, 25, -9, -17, 0, 38, 24, -13, 49, -20, -4, 0, 10, 26, 19, -51, 1, 17, 47, -5, -19, 32, -5, -39, -32, 13, -29, -30, -40, 19, -17, 6, 5, -3, -17, -3, 16, -15, 16, 30, -11, -37, -9, 24, -18, -27, 33, -22, -13, -22, -12, -29, 13, -16, 11, -25, -26, 18, -16, -29, 15, -43, 18, -42, -43, -6, 34, -2, 32, -2, 21, -14, -24, 34, 10, -11, 21, -8, 44, 43, 45, 31, 37, -26, 1, 15, -25, -4, 38, -5, 19, -36, -18, -9, -9, -4, 26, -24, -18, 31, -40, 38, -9, 35, 49, -1, 17, 26, 7, 23, -2, 17, -38, -5, -6, 19, 17, -33, -27, -20, 51, -2, -45, -34, 18, 53, 5, 29, -41, 32, 42, -31, 18, 37, -24, -36, 30, 33, 10, 5, 44, 42, -24, 29, -26, -10, -5, 24, -30, 18, -18, -24, 40, -18, -11, -4, 2, -3, -1, -5, -39, 36, 51, 11, -21, 17, -32, -3, 1, 5, 40, 24, 29, 13, -14, 23, -22, 3, -8, -10, 8, 14, -41, -32, 8, 16, 17, -21, -23, -20, -27, 40, -8, 7, -22, 6, 0, 2, -5, -35, -23, 25, 8, 13, 37, -6, 44, -21, 18, -14, 2, 45, 18, 28, -22, -16, 17, 3, -10, -21, -47, 16, -44, 23, -20, 4, -5, -41, -34, 5, -41, 21, 11, -47, -6, 6, 8, 49, 34, -3, -36, -16, 19, 19, 13, -5, 14, 7, 18, 30, 15, -40, -26, -13, -21, 5, -40, -36, -37, -35, 9, 26, -27, 14, -33, -24, -32, 4, 6, -13, -40, -36, 7, -25, -23, -25, -17, 14, -21, 3, -25, -13, -24, 11, -18, -20, -22, -12, 7, -43, -22, -44, -22, -34, -16, -2, -9, 4, -12, -14, 12, -20, -6, -22, 0, 23, 24, -28, -5, -20, 18, -12, -9, 15, -15, -25, -2, -13, 5, -32, -27, 21, 24, -14, 35, -5, -26, 15, 4, 9, 32, -39, -9, 22, -21, 13, -38, -30, 18, -2, 0, 7, -11, -30, -33, 10, 6, 15, -5, 1, 27, -20, -8, -30, -44, -35, -40, 9, -39, -1, -16, 7, 14, -23, -42, 18, -23, -23, 10, -2, 14, -10, -19, 3, 17, -24, -31, -33, -36, 11, -28, -36, 10, 7, -18, -27, 7, 22, -29, -36, -24, 7, -15, -11, -9, -30, -16, -24, -16, 5, -18, -7, -12, -1, 22, 3, 8, 59, 6, 15, 35, 2, -42, 36, 20, -17, 27, -1, 1, -38, -25, -26, -26, 44, 5, -11, -26, 20, 9, -37, 36, -3, 29, 55, -21, -47, 28, -88, 41, -15, 28, 3, -54, -8, 9, -28, -27, 42, 21, -7, 9, -2, -39, -2, -59, 35, 17, -4, -40, -24, 49, -13, 4, 34, 12, 28, -27, 4, 44, 6, -34, -11, 0, -51, 52, -19, 5, 18, -27, 28, 17, -12, 40, 16, -38, -30, 89, 22, -9, 51, 23, -13, 10, -20, -9, -24, 5, -33, -3, 37, 35, -17, 41, -30, 27, -8, 3, 10, 18, -2, -6, 6, 23, 25, -29, 11, -21, 31, -19, -14, -23, -3, 28, -37, -28, -17, 12, -8, -4, -47, 4, 28, 17, -53, -6, 36, -27, -23, 27, -2, -7, 23, -12, 6, -28, -26, 1, 7, 24, 37, -17, 15, 11, -11, 25, 12, -3, -24, -48, 16, 6, 2, -40, 21, 19, -66, 47, 34, 17, 6, -29, -18, 30, -32, -22, 4, 22, 22, -29, -20, -1, -19, -6, -33, -21, -15, -48, -8, -39, -41, 4, -24, 8, 0, -52, -34, 40, 16, -1, -8, 6, 5, -24, -35, 18, 16, -26, -39, 7, -27, 3, 31, -32, 1, 33, 35, -17, -33, -27, -2, -6, 27, -32, 5, -11, -56, -14, -25, 27, 13, -57, 42, -65, -22, 18, -26, -7, -15, 15, 58, -34, 37, -12, -40, 31, -40, -1, -24, 15, -51, -28, -28, -31, 34, 26, -32, 11, 30, -15, 2, 2, 8, -36, 4, -16, -26, 8, -5, -19, 41, -52, 25, 41, 7, -21, -17, 5, -4, 11, -5, 5, -44, -25, 24, -6, 5, -26, 30, 16, 17, 3, 47, 10, 15, 27, -2, 27, 2, -24, -46, 39, 15, 1, 2, 27, -27, -20, -10, 7, -4, -64, -14, -38, 33, 4, -28, 5, 8, -9, 11, -41, -11, -1, -13, -5, 42, 41, 21, 16, 9, 1, -26, -7, 26, -53, -6, 13, -9, 6, -11, 36, 37, -14, -24, 38, -1, 12, 15, 7, 46, 6, -11, 18, -10, 19, -10, 26, 31, 35, 21, -6, -5, -56, -24, -2, -27, 15, -25, -58, 1, -47, -27, 2, 11, 47, 6, -34, 34, 42, -24, -16, 10, 44, -22, 2, -13, -6, 18, 12, 48, -33, 43, -20, -17, -37, 26, 11, -31, 45, -4, -48, -34, 8, -10, -1, 48, -12, -15, 17, -12, -33, 2, -14, -16, -32, -14, 13, 52, -24, 65, 26, 32, 13, 37, 21, 7, -12, 51, 13, 20, -4, 5, -19, 40, 22, -24, -11, 23, -11, 13, 25, 14, -1, -47, 31, -4, 11, 9, -41, 8, -12, 10, 14, 2, 11, 30, -32, 30, 2, 31, 17, -43, -11, 40, -20, 16, 31, -31, 50, 17, -29, -1, 34, -29, -41, -16, 6, -18, -15, 35, 29, -48, -48, 21, 15, 20, 19, 5, 44, -16, 20, -17, -25, -34, 24, -12, 43, 23, -1, -5, 6, -39, 1, -3, 13, -12, -59, -47, -6, 4, 9, -17, -19, -23, 21, 0, 0, 6, -25, -24, -21, -3, 16, 30, -14, -16, -2, -2, 12, 6, -19, -5, 0, -35, -12, -21, 1, -14, 39, 30, 13, 6, 3, -2, -16, -34, 63, 33, 19, -1, 15, -34, 19, -5, -5, 24, 2, 22, 26, 3, -2, -36, -56, -35, -6, -47, 37, -41, 23, -21, 6, 12, -46, 29, -20, -14, 4, 18, 16, 17, 7, -6, -8, 31, -1, -31, 1, -33, 6, -22, -2, 19, -47, 29, -9, 19, 22, -20, -13, 5, 4, 1, 2, -27, 15, -38, 3, -11, 36, 31, 5, 31, -39, -17, 4, -7, 1, -6, -5, 17, 2, -42, -8, -12, 26, -20, 20, 41, -21, 2, 10, 0, 13, 43, 43, -9, -6, -2, -24, -20, 39, -12, -22, 12, -54, -24, -2, -46, 4, -41, 33, 9, -37, 2, -27, 14, -18, -16, 43, 6, -16, 8, -31, 11, 25, 32, -17, 3, -36, -31, 31, -15, -3, 26, 17, -3, 6, 2, -11, -11, 23, 24, 15, 5, 24, 30, -17, 3, 37, 46, 13, 16, 7, -7, -7, 34, 25, -11, 14, -4, -56, -11, -6, -4, -23, -15, 40, -24, 18, 26, 28, 57, 35, -28, 28, -14, -9, 8, 11, 33, -53, -18, -23, -14, 43, -40, 21, 42, 27, -15, 8, -4, -3, 27, 5, 19, -21, 24, -69, 19, 36, -52, 0, 18, -10, -5, -37, 2, 52, -8, -38, 23, -16, -9, 5, -40, -36, 22, 10, -76, 12, -87, 11, 4, 45, -4, -13, -14, 22, -13, -2, -1, -26, 18, 53, -62, -49, 36, 12, -37, 17, 47, -4, -30, 0, -36, 1, -40, -59, -15, -16, -8, 32, 37, 15, -36, -42, 23, -23, 38, -15, -36, -2, 20, -20, -24, 13, 16, -52, -18, -6, -23, -34, -14, 83, -68, 31, 14, -38, 6, 10, 10, 42, 13, -16, -12, 46, -12, -6, 14, 10, 18, -59, 12, -5, 35, -26, -53, -33, -23, -8, 0, -8, -9, -6, 91, -15, -6, 25, 56, -1, -32, 8, -21, -18, 24, 8, 29, -36, -20, -6, -4, 24, -23, 18, -34, 5, -21, 19, 27, -3, -22, -31, 33, -58, -19, -76, 27, 43, 36, -12, -9, 2, -12, -30, 2, 2, 39, -2, 17, -51, 14, -8, 30, -25, -39, -37, -5, 9, -25, 17, 34, -7, -18, 15, -17, -17, 7, -6, -3, 28, 9, -5, -30, -19, -15, -4, 27, 5, -24, -36, 19, 0, -39, 9, -16, -4, -1, -4, 8, 16, 15, -9, -42, -29, -1, 30, -23, 32, -1, -9, -12, 6, 16, 42, 0, -5, 30, -7, -55, -49, 22, -9, -21, -35, -72, 30, -1, 13, -21, 9, 17, 13, -21, 34, -4, 20, 22, -17, -65, 26, -14, 23, -21, 22, 11, -22, -35, 14, -28, 3, -16, -5, -58, -23, 42, 23, -68, 25, 9, -27, 61, 10, 29, 34, -13, -37, 11, -65, 16, -16, -8, -13, -7, -14, -28, -32, 41, -3, 12, 37, -8, 18, -51, -7, -1, 6, 3, 10, 21, -7, -12, -24, 15, -20, 42, -34, 17, -21, -41, 7, 18, 11, -51, 28, -11, -30, -23, 3, 26, 15, 2, 36, 20, -33, 30, 47, -14, -33, 12, 38, -12, -22, 18, -23, -11, -38, -23, 9, 10, 19, -23, 13, -36, -44, 0, -13, -1, -17, 54, 7, -39, 1, -29, -21, 10, 28, 6, 12, 22, -27, 35, -11, -32, -21, -39, 27, 0, -27, 15, 9, 12, -27, 27, 23, -24, 11, 54, 14, 8, 30, 35, 20, 14, 39, 1, -1, 25, -31, 28, 2, 18, -8, -5, 8, -8, 6, 9, 12, -67, -26, 13, 31, -17, 31, -25, -15, -37, -21, 14, -16, -2, -21, 28, 10, 42, 32, -11, 28, 42, 13, 28, -27, -17, 41, -31, -1, 14, 41, -14, -9, 14, 15, -6, 0, -24, -24, -9, 11, 20, 3, 26, 11, 1, 2, -10, -10, 25, 29, -40, 49, -18, -24, -42, -9, 30, 5, -10, -13, -6, -22, 30, -5, -3, -31, 21, -30, -26, 5, -2, -14, -28, -13, 16, -34, 38, -32, 2, -36, 21, 0, -58, 47, -49, -7, -34, -28, -53, -8, 12, -16, 18, 6, 2, -20, -10, -28, 12, 4, -80, -20, -24, -19, -9, 8, -15, -36, 14, -44, 33, -41, 6, 12, 20, -36, -13, 12, -37, -12, -33, -64, 8, 25, -45, 32, -14, -2, -25, 58, -14, 11, 24, 34, 64, 9, -12, -29, -9, 7, -34, 17, 19, 11, -48, 10, 2, -11, 12, -10, -14, 15, -10, 18, 7, 10, -15, -1, 30, 3, -12, -22, 1, 24, 16, 31, 14, 8, 3, -8, -7, -41, -36, -29, 28, -26, -4, -19, 1, 40, 3, 4, 20, 11, 1, -43, 3, 43, 24, 20, 27, 46, 5, 2, 18, -5, 22, -11, 39, 12, 34, 40, 3, 22, -9, 29, -25, 28, 28, -12, 8, -8, -28, 37, 34, 24, 9, 28, 1, 41, -3, 77, 0, 5, 25, -14, -27, -2, 34, 36, 16, 17, -3, -8, 23, 10, -8, -13, -3, -11, -10, 9, 19, -46, -17, -14, -25, 29, -36, 30, -19, 4, -21, 23, -33, 41, -13, -28, 43, 43, 24, 35, 14, -35, 40, 31, -26, -38, 29, -12, 2, -13, -29, 11, 41, 17, -5, 14, -4, 24, 32, 5, 52, 1, -38, 28, -1, -24, 26, 0, 11, 37, -14, -8, 21, -25, 14, -28, 20, 25, -15, -12, -5, 33, -2, 6, -6, -6, -31, 14, -31, 43, 14, -52, -19, -30, -13, 8, 38, -12, -31, 13, -14, -46, 36, 12, -35, -25, 41, -7, 27, -42, -7, -40, 23, -30, 35, 3, 45, 13, 7, 26, 32, -17, 22, -13, 31, 58, -11, -28, 33, 24, 10, 19, -9, -20, 17, 18, -24, -14, 2, 30, 22, -42, 22, -57, -6, -36, 21, -3, -8, 42, -24, 11, -29, -28, 11, 1, 31, 0, 4, 15, 2, 2, 10, -39, 41, 15, -7, -30, 12, -38, -9, 17, -24, 34, 41, -14, 38, -26, 32, -16, -33, -13, 37, 7, 9, 48, -17, 15, -13, 20, -14, 31, -28, 58, 41, -2, -29, -13, 5, -28, 12, 24, -28, -24, 24, -28, -21, 2, 26, 43, -3, -20, -37, -19, -11, 23, 9, -40, -6, 11, 4, 5, 9, 3, 26, -2, -15, -20, 0, 22, 24, 14, 16, -34, -34, 5, -22, -30, -9, 14, -14, -5, -4, 40, 40, 9, -12, 7, 8, -24, 20, 40, 26, -20, -50, -5, 34, 5, -45, -20, 5, 17, -1, -40, -21, -16, 21, -42, -32, -4, 37, 0, -17, 20, 3, -34, -28, 4, -70, -29, 12, 10, -1, -11, -14, -21, -40, -13, -38, -7, 17, 47, -34, 22, 13, 13, 44, 36, 7, 8, 18, -5, 15, 28, -4, 41, 1, -14, -10, 0, 14, 29, 20, -17, 33, 6, -3, -21, -11, -22, 36, -3, 18, 14, -31, -19, 9, 36, -26, 42, 32, 2, 44, -21, -40, 11, -12, 6, -35, -12, -7, 24, -13, -35, -4, -9, -3, -50, -14, 1, 24, 14, -17, 26, 39, -33, 17, 2, 29, 32, -3, -18, -8, 0, 21, 24, -8, 6, 10, -2, 0, -8, -31, 2, 22, 18, -19, -4, -18, -21, 30, -35, 21, -4, 27, 8, 25, 21, 1, -6, 18, -11, -5, -1, -40, 19, 40, 41, -14, 42, -19, 62, -26, -8, 17, -1, -29, 8, 44, -8, 49, -32, -8, -20, 27, 38, -16, -32, 21, -28, -30, 55, -21, -15, -19, -1, 49, 38, -10, 7, -21, 15, -51, -32, 16, 8, -1, -20, 5, 3, 36, -15, -27, 50, 11, 12, 18, 20, 1, 18, 31, -15, 27, -30, 18, -5, -37, 9, -8, -32, -46, -20, -10, 13, 18, -11, 40, 0, -14, -36, -23, 39, -22, -7, 11, -38, -6, -42, 0, -26, -36, 8, -26, -5, 43, 48, -11, 36, -9, -33, -13, 35, -31, -12, -7, -34, 16, 1, 22, 14, 6, -5, -10, 19, -14, 11, -3, 36, 23, 46, -44, 9, -46, 19, -33, -2, 17, -23, 1, -9, -23, -2, -21, -40, 34, 4, 37, -43, -24, -24, 11, 24, 30, 31, 5, 30, 27, 20, -24, 10, 32, 46, -35, 3, 9, -4, 7, -10, 1, -15, 7, 35, -11, 30, 24, 10, 3, 47, -22, -8, -10, -20, -8, -13, -27, -46, -20, -31, 17, 71, 37, 11, -29, -6, 18, -9, 12, 7, 20, -41, 22, -11, -5, 18, -2, -4, -11, 30, 21, -16, -24, 34, 41, 12, -25, -25, -19, -29, 49, 35, 3, 18, 9, -13, 33, -38, 28, -29, 34, -10, 7, -31, -41, 26, 13, 10, -35, -26, 8, 37, 39, 1, 19, -14, 17, -29, -14, -11, 50, -29, 20, -23, -19, 33, -23, 21, -10, 17, -19, -18, 17, 46, 27, 23, -25, -29, -2, 6, 51, -36, 16, -20, 35, -6, 25, 6, -44, 32, -44, 40, -53, 20, 27, 16, -6, -28, 3, 31, 18, 2, 14, -2, -4, -8, 22, -29, -13, -12, 39, 37, -9, 8, -9, 26, -29, 8, 0, 27, -8, -22, 41, -6, -27, 28, 16, -62, 29, 40, 34, 49, 22, -24, 7, -7, -34, 6, 37, 20, -6, 33, -14, 21, 0, 0, -6, 34, -16, -19, 4, 8, -14, -36, -14, 16, 17, 13, 2, 2, -24, -16, 27, -18, -6, -46, -16, -27, -32, -23, -25, -50, -13, -18, -21, 11, -2, 43, 17, -8, -4, -43, -44, -11, -8, 35, 3, 21, 15, -17, -2, 44, 12, -58, 1, 11, -32, 8, -29, -10, -23, -8, 9, -10, -25, 27, 37, -8, 39, -18, -24, -4, 72, -10, -24, -15, -20, -12, 51, 45, 13, 2, 11, -35, 28, 22, 31, 28, 29, 6, 0, 21, -22, 19, 53, -4, 1, -3, 21, -7, 18, -39, -17, 19, 10, -9, -35, -16, 59, 32, 1, 13, -40, -24, -60, -7, 0, -29, 41, 19, -31, 3, 22, 57, -17, 28, -49, -31, 8, 47, 26, -18, -43, 26, -15, 4, -20, -53, -46, -20, 15, -12, -19, 12, 4, -49, -26, -40, -30, -4, -11, 30, 27, -54, -33, -12, 34, -70, -15, 1, 4, 11, -19, -15, 26, -67, 45, 17, -13, 22, 34, 30, 26, -28, 31, -5, 38, 26, 67, 24, -56, 0, 32, -12, 10, -28, -22, -15, 45, -51, 36, 15, 6, -31, -53, -19, 24, -8, 64, -45, 9, -11, -18, -14, -17, -30, -20, -31, -53, 0, 2, 16, -23, 14, -22, -17, 54, 21, 5, 21, -1, -41, 62, -5, 1, -8, 55, 6, -14, -23, -5, -13, -9, -35, -38, 43, -97, -36, 32, -3, 31, -19, 1, 25, -8, -8, -4, 13, -5, -9, -15, -5, -14, -19, 9, 26, 18, -9, 39, -11, 23, -32, 4, 17, -32, 16, 6, 51, 44, 15, -45, -50, -40, 26, -40, -14, 25, -19, 36, -21, 1, 31, 25, 30, -21, 35, -11, -7, 26, 16, -16, 13, 0, 25, -5, -41, -26, 13, -14, 19, 3, -76, -38, -4, -25, -22, 20, -12, 11, 38, 31, -5, 15, -1, -8, 2, 13, 37, -64, -19, -21, 15, -11, -42, 42, 12, 21, -36, -19, 19, -35, 0, -10, 23, 12, -25, 22, 15, -6, 42, -3, 2, -30, -25, 16, 3, -14, -7, -15, 7, -41, -29, -44, 7, -19, -13, 25, -25, 32, -60, -37, 19, 8, 21, 43, 22, 1, 16, 26, -17, -4, -39, -3, 20, -27, -3, -17, 34, -7, -49, -30, 10, -2, -3, -24, -12, -20, -47, -63, 21, -2, 13, -42, -53, -15, -30, -3, -6, 14, -12, 26, 53, -2, -24, 26, -32, -12, 67, 36, -2, -17, 60, 26, -22, -35, 38, -37, 25, 22, -8, 3, -23, -43, -22, 24, -4, -37, -40, -34, 23, 9, 17, -33, 17, -3, 8, 18, 13, 70, 23, -12, -55, -56, -23, 8, -6, -25, 50, -45, 32, -49, 11, -34, 2, 6, -7, -25, 48, -11, -7, -35, 23, -44, -8, -24, -9, -23, -45, -8, -35, 10, -18, -3, 22, -19, 17, -13, -23, 10, -24, 37, -14, -50, -8, 13, 82, 7, 12, 41, -32, -7, -25, 15, 3, 0, -24, 51, 19, -56, -19, 19, 40, -64, 40, 6, 34, 4, -34, -8, 23, -2, 32, 11, 5, -46, 37, -14, -51, 45, 4, -39, -1, 2, 11, 24, -25, -29, -50, -11, 11, 14, -14, -39, 40, 46, -34, 13, -36, -17, -19, -20, -64, 1, 4, 33, 0, 20, -25, -2, 26, -15, -59, -11, 0, 31, -96, 11, -7, 49, 36, -12, -91, -1, 0, -20, 33, 39, -17, -14, -67, -14, 25, 4, 19, -13, 6, -38, -17, -2, 36, -5, 22, 12, -21, -31, 18, -6, 42, -15, -31, 16, -5, -31, 8, 7, 53, -30, 45, -3, -48, -30, -6, 42, -51, -14, -2, -16, -15, -13, -37, -2, -25, 38, -41, -9, 4, 17, -41, -24, -72, 39, 45, -19, 10, 17, -2, 11, 6, -5, 17, 32, 21, 23, -4, 17, -38, 47, -17, 13, -6, -18, -10, -4, -10, 29, 2, -2, -38, -46, -19, 0, 37, 17, -21, -50, 41, -19, 16, 9, -12, 13, -11, -19, -27, 30, -23, -24, 8, 84, -17, 69, 37, 3, 8, -39, 31, -18, 19, -88, -13, -13, -5, 4, -21, 33, 2, 24, -20, -24, -23, -5, 24, 0, 4, -15, -4, -25, 2, -5, -43, 4, -7, 9, 7, -12, -46, 21, -41, -6, 0, 61, 41, -31, 10, 19, 39, 52, 12, -28, -36, -9, 24, -8, 14, 43, 4, 8, 5, 11, -6, -37, -26, -4, -27, -19, 21, -46, 23, -13, 47, 7, -10, -20, -6, -37, 6, -38, 2, 24, -27, -11, -29, 1, 42, -16, 23, 10, -37, 41, 0, 16, -40, -16, 1, 39, -12, 4, -1, 2, -17, -9, -14, 22, 26, 22, -31, -6, -31, 5, -34, 26, -13, 25, 51, -1, 33, -48, -17, 27, -15, 10, 13, 7, -21, 11, -32, -63, -41, 35, -4, 4, 30, 22, -28, -55, -22, -23, 28, 26, -48, -19, -5, 12, 39, -63, 26, -14, -23, -33, 63, 5, -17, 39, 2, -24, -13, 14, -40, 15, 12, -24, -53, -13, 24, -24, 6, 12, 30, -4, 1, 15, 20, 30, -29, 28, -23, -17, 9, -10, 6, -51, 2, -66, 5, 10, 20, 20, 53, -28, 21, 15, -24, -23, -15, 3, -26, 13, 4, 34, 51, -1, -15, -26, 25, -13, -7, 28, -30, -10, -14, -33, -43, -25, 1, 7, 6, -18, -1, 6, -19, 6, -11, 30, 2, -22, -9, 15, -20, 16, 43, -28, -18, -8, -26, -20, 63, -14, 58, -38, -39, -17, 6, 33, -5, -2, -39, -11, 4, -62, -19, 54, -20, -22, 16, 17, 19, -36, 12, -27, 1, -6, -5, 89, -10, 7, -22, -7, 45, -22, 27, -21, -9, -69, 1, -45, 5, 1, -10, -5, -22, 33, -39, -8, 34, -70, 17, 29, 15, -31, 19, 20, 29, -11, 13, -34, 1, 15, 38, -23, -32, 4, 22, -19, -18, 0, 9, 52, 11, -8, -6, 45, -14, 32, 2, -9, 25, -4, 13, 7, -1, 24, 19, 47, 37, 21, 16, 10, 2, -48, 10, 26, -22, -35, 10, 16, -18, -13, -17, 31, 34, -32, -23, 5, 0, 21, 34, 30, -13, -13, 41, -6, -8, -23, 8, 31, 31, -23, -8, 23, -9, 9, 4, 9, 6, 3, 37, -36, -2, 3, -6, 16, -30, 21, 25, 12, -52, -38, 5, -10, -35, -29, 26, 5, -3, -1, 8, 24, -21, 26, -25, 0, -19, 0, 23, 31, 1, 29, 7, 21, 0, -32, 3, -8, -47, 40, 3, 0, 30, 31, 38, -21, -26, 17, -22, -4, -9, 36, -18, -23, 29, 0, -35, 1, -41, 18, 10, 1, -48, 16, 19, 23, 24, 10, -35, 24, 29, 37, 13, -4, 22, -26, 0, 24, 7, -12, 16, 62, 0, -45, -20, -3, -23, -25, 14, 31, 34, 6, 28, 38, -48, 36, -38, 0, 37, -15, -16, 31, 36, -8, 30, -8, -7, -8, -27, -8, 53, -10, -10, 24, 21, 0, -18, 25, -16, -9, -4, 29, -22, -5, -23, 8, 1, 32, 32, -11, 41, -35, -22, -26, 14, -30, 32, 12, 10, -11, 29, -5, -2, 14, 15, -41, -22, 43, 17, 19, -10, -8, 16, -29, -23, 17, 20, 36, 43, 9, -26, 38, -23, -16, -24, -15, 26, 46, 21, 10, 21, 19, -15, -7, 0, -3, 22, 17, -23, -28, -6, 16, -43, 5, 17, 1, 28, -46, 20, -52, 3, 31, -49, 22, -27, -18, -1, -19, 3, 16, -18, -33, 4, 2, -5, 20, -37, -4, 39, 4, -15, -68, -19, 25, -29, 22, -11, 26, -30, -24, 14, 10, -35, 37, -9, 2, 1, -26, -26, 29, 27, -4, -21, 19, -2, 28, 0, -28, 24, 34, -10, -24, -30, 21, -18, 36, 23, 32, -16, -6, 32, -10, 11, 7, -32, 47, 49, 6, -37, -19, -1, -6, 34, -16, -20, 21, -14, -30, 36, -19, 7, 50, 4, 20, -30, -3, 3, -11, -30, 24, -4, -41, 40, 23, -19, -15, 31, 8, 25, 7, -8, 29, 31, -11, -30, 36, -17, -4, 0, 36, -25, -18, 5, -30, -29, -28, 47, 21, 8, -6, 38, -10, 14, 33, -21, 18, 15, -22, 29, -18, -2, 11, 0, -29, 40, -16, -2, 12, 3, -1, -22, -26, 30, 13, -10, -6, -33, 6, -48, 23, 31, -13, 3, -50, 15, -3, -16, 28, 37, -12, 9, -26, 1, 44, 11, -10, -34, -20, -3, -11, 16, 12, 10, -28, -12, -2, -4, -48, 18, 16, 40, 11, -20, -25, -49, -3, -1, 41, -31, -26, -7, -35, -7, -43, 17, -16, -26, 17, 3, 28, -11, -62, 22, -38, -18, -23, 10, -40, -51, -15, -25, -1, 19, 0, -56, -33, 12, 5, -27, 3, -3, -18, 6, 0, -64, -6, -23, 8, -19, -23, -7, 31, 10, -20, -48, -14, -14, 2, -20, -17, -15, -43, 1, -35, -13, 23, 16, 1, 52, -6, -31, -6, -36, -39, -36, -18, -34, 8, 21, -4, 20, -18, -25, -7, 24, 11, -20, -21, 14, 19, 20, -1, -6, -6, -34, -45, -11, 24, 49, -29, 4, 41, 2, -30, -32, -55, -16, -18, -22, 21, -20, -17, -2, 15, -19, -4, 9, 20, -2, 9, 1, -15, -18, 4, 9, -4, 13, -7, -37, -18, -18, -19, 33, -8, -57, -48, -51, 11, -5, -18, 19, -39, -8, 9, 0, -12, 6, 0, -59, 11, 4, 5, -25, 37, 6, 32, 21, -19, -16, -45, 1, -13, -34, -4, 9, 8, -19, 29, -43, -14, -20, 12, -26, -7, -51, 17, 4, -41, -36, -1, -10, 7, 23, 7, 7, 8, 22, 18, 48, 9, -17, -15, 25, -40, 9, 23, 1, 42, 29, -8, -19, -4, 29, 0, 42, 0, 7, -12, -26, 12, 47, -20, 14, 15, -11, 48, -27, 11, -50, 15, -24, -47, 12, 10, 41, -13, 6, 3, 20, -22, -27, -3, 2, 2, 33, 0, 0, 13, 7, -61, -36, -41, -4, -50, -22, 10, -28, -40, -5, -26, -11, 15, 4, -3, 40, -43, 10, -44, 21, -6, -31, -22, -34, 9, -13, 2, -11, -31, -35, 21, 14, 49, 10, 19, 19, 32, 10, -7, 1, 24, -40, -5, -14, -32, 40, 19, -28, -5, -38, 2, 55, -18, -23, 0, -16, 27, -2, 22, -33, 3, -36, -2, 32, 9, 12, 13, 5, -15, 33, -3, 17, 14, -19, 13, -18, 30, -50, 28, 6, 16, -46, 20, 22, -19, 43, -4, -17, -6, 56, 30, 22, 33, -34, -37, -16, -44, -30, 2, 39, -14, -12, -22, 35, 5, 28, -1, 35, 31, 1, 27, 72, -17, -19, 34, 16, 8, -27, 9, 6, 7, 31, -13, -16, -23, -15, -39, 30, -6, 15, -1, -17, -8, -17, -12, 29, 19, 37, -48, -26, 32, 3, 11, 8, 10, 5, 16, 12, 21, -2, 32, 29, -16, -5, 36, -3, 34, -14, -6, -33, -7, 28, 42, -23, -11, 14, 29, -32, 10, -48, -13, 7, 16, 51, 44, -9, 3, 7, -19, 28, -1, 16, -27, 49, -39, 14, -10, -44, 15, -13, 36, 19, 19, 41, 4, 5, -15, 10, 41, -15, 25, 11, 37, 51, 41, -3, 13, 6, 23, 45, -15, 16, -24, -26, -5, 20, 21, 21, -40, 21, 14, 50, 9, 19, 31, 57, -10, 22, -19, 21, 12, -24, -12, 48, -43, -5, -9, -13, -22, -82, 3, -3, -14, 25, 28, -13, 14, 27, 30, -29, 12, 23, 4, -14, -7, 11, -36, 12, -43, -1, -15, 11, 29, -5, 33, -35, -44, -33, -54, -50, 2, -27, -7, -44, 18, 6, 9, 6, 13, 48, -39, -30, 19, -35, 12, -30, -9, 18, -40, -24, 26, -28, 20, -35, -24, 29, 19, -46, 11, -27, 25, -15, -3, -22, 36, 19, -1, 12, 6, 15, 20, -49, 23, -22, -2, 3, 37, 6, 8, 1, -16, -39, -29, -14, 9, -10, 27, 22, -1, -4, 21, 6, -19, -27, 6, 2, -13, -55, -17, -23, -25, -38, 14, 27, -54, 12, 6, -65, -21, -7, 27, 18, 9, 5, -7, 0, 0, -9, -42, -28, -20, -20, -12, -23, 12, -20, 3, -31, 18, -30, -24, -3, 12, -20, 37, 18, 33, 27, -12, 45, 25, 34, 0, -2, 22, 5, 5, 57, -20, 36, -7, 46, -24, 6, -37, -42, 28, -3, -16, -52, -16, -43, 37, -10, 26, -8, -26, 10, -13, 25, 27, -19, -10, -14, 0, 41, -34, 12, -5, -1, -26, -2, -10, -33, 11, 5, -17, -15, -44, -47, 4, -23, 31, -8, -31, 7, 23, 47, 27, -15, 2, -8, 45, 33, -8, 35, -23, -27, -3, 21, 38, 30, -23, -15, -32, -23, -32, 12, 12, 11, 8, 30, -6, -5, 32, 16, 30, 4, -26, -22, 53, 24, -13, 11, -53, -5, -7, 26, -1, -13, 23, 11, 7, -60, -18, 40, -52, 20, -42, -50, 7, 29, -14, -37, -10, 10, 1, 38, 24, -26, -43, -17, -18, 0, 29, -16, -26, 17, -7, -51, 41, 11, -47, 9, -14, 34, 5, 21, -40, -21, 44, 54, 5, 29, 15, -20, 18, -28, 2, 30, 0, 3, -14, 12, 16, 23, 4, 12, 1, 50, 19, -5, 46, 1, -6, 40, 27, -2, -3, 23, 19, -8, -14, 55, 18, 30, 52, -4, -14, 16, 5, 4, -40, 27, 35, -10, -19, -26, -29, -9, -16, 4, 19, -20, 25, 12, 5, 9, 26, -6, -5, -8, 2, 17, -12, 23, -33, -5, 25, 4, 45, -37, -39, 12, 2, -22, 36, 3, 17, 16, 36, 26, -32, -29, -1, 32, 20, -15, -11, 11, -25, 14, -49, 17, -12, 19, 30, -38, 15, -14, 10, -32, 14, 25, 30, -35, -17, 3, -33, -18, 1, 23, -89, 22, 28, -30, 27, -35, 24, 14, -10, -53, -15, 39, -30, 15, 9, -3, -14, 4, 41, -26, -20, -30, 26, -53, 7, 22, 30, -35, -16, 23, 32, 5, 9, 0, -23, 42, -43, -6, -9, -40, -11, 8, 18, 42, 30, 41, -43, 44, 3, 42, -38, 13, 30, -13, 1, 17, 65, -34, 7, 35, 2, -19, 20, -28, -30, 27, 21, 22, -7, 7, 2, -42, -16, 7, -33, -40, 8, 6, -21, -24, 8, 36, -33, -2, 21, -1, 26, 30, -6, 21, -35, 13, 13, 28, 14, 25, -23, 28, -23, -65, -1, 17, -10, 12, -23, -20, -21, -26, -16, 12, 6, -14, -19, -5, 3, -12, 36, 34, 0, 13, -14, -19, -45, -11, -40, -21, -11, 18, 19, -22, 32, -38, 5, 25, 8, -26, 0, -34, 7, 3, -39, -17, -82, 28, 7, -2, 5, 12, 21, 40, -19, 11, 21, -9, -28, 3, -26, 47, 49, -8, -11, 16, -22, -8, -13, -13, -26, 26, -10, -24, -45, 27, 4, -22, -10, 27, 15, 12, -6, -8, 10, -16, 23, 13, 7, -32, -1, -10, 11, 10, 24, -11, -54, 51, 8, -2, -32, -13, 42, -14, 16, 32, 13, -10, -45, 16, -6, 8, 13, 9, 4, -33, 14, 30, -59, 43, 34, -6, 34, -34, -11, 41, -5, -10, 14, 25, 44, -20, 45, 10, 42, 7, 16, 41, -3, -15, -19, 2, 8, -22, 18, 53, -26, -25, 25, -9, -2, 44, 9, -22, -27, -16, -34, 64, -8, -4, -33, 10, 5, 13, -33, 3, -47, 38, 27, -27, 28, 27, 46, 22, 12, 6, 28, 30, -5, 30, 6, -41, 13, 48, -32, 9, 17, 11, -66, 23, 38, 4, 6, 39, 13, -15, -12, -17, -38, 33, -45, -18, -35, -20, -40, 43, -15, 46, 40, -34, 12, -37, 17, -51, 44, 4, 0, 34, -28, -49, -14, -17, 19, -26, -2, -45, 4, 13, 0, -15, -56, -23, 8, 8, 11, 40, 40, 15, -48, 2, 43, -26, -15, -11, -54, 30, 8, 28, 44, -37, 19, 20, 10, -28, 16, 6, -9, 14, 20, 13, -14, 29, -21, -8, 16, 43, -22, -40, -9, -10, -35, 23, 41, 8, -44, 3, -27, -45, 3, 26, -36, 8, -35, -17, 12, 45, 5, 10, -39, 22, 8, -3, 25, -3, 4, 1, -16, -1, 3, -35, 42, -11, 18, 5, 23, -16, 35, 26, 28, 27, 10, -39, -42, 32, -5, 13, -5, -30, 8, 4, 23, -20, 9, -10, 31, 1, 30, 10, 52, -3, 21, -3, 22, -3, 10, -5, -30, 6, -7, 29, -40, 46, -46, 17, 18, 4, -6, -7, 22, -13, -32, -13, 34, -19, 4, 21, -1, -30, 16, 26, -2, 8, 27, 23, -22, 18, 18, -42, 12, 6, -38, -28, 18, -21, -11, -19, 15, -38, 17, 4, -12, -4, -23, -22, -45, -42, -2, -4, -17, -21, -6, -42, 17, 13, -33, -33, 4, 57, 5, -55, 3, -42, -30, -3, -21, 15, 0, 40, -44, 3, 3, 12, -59, -29, -26, -25, 9, -45, -31, 2, 8, 15, 29, -65, -13, -17, -1, 44, -2, -2, 0, 7, 13, -28, 53, -12, -38, 30, 39, 16, -18, -6, 23, -23, -32, -26, 57, -18, -9, -9, -14, 26, 4, 12, -4, -26, -30, 33, -17, 26, -9, 3, 8, 19, -48, 46, -15, -24, -16, -26, -26, 26, 12, 6, -20, -18, 2, -8, -4, 18, -22, 17, 28, -12, -27, 9, 2, -6, -1, -39, -3, 31, 31, -40, -33, 0, -15, -22, -32, 48, 28, -67, -5, 26, -16, -14, -5, 7, 10, 17, 26, 23, 29, -7, 43, -4, 7, 27, -71, -18, -28, 21, -20, 12, -39, 26, -15, 27, -21, -37, -25, -13, 12, -39, 35, 51, -40, -15, -2, -28, -3, 21, -10, 38, 7, -31, -23, -22, -31, -14, -16, -2, -18, 3, -29, -18, -43, 15, -20, 5, -34, 24, 15, -10, 15, -11, -42, 25, -10, 9, 16, -56, -10, 31, -5, 8, 57, -24, 34, -2, -66, -24, -18, 23, 13, -1, 38, -3, 22, 8, 11, 33, -10, 53, -6, 29, -18, 3, -8, -34, -25, -6, -37, 4, -40, 20, 22, 23, 5, 21, -36, 15, -12, 10, 27, 16, 1, 14, -20, -13, 14, -23, -6, -26, -6, 24, -49, 8, -4, 8, -28, 1, -47, 16, -31, 18, 36, -20, 5, 13, -4, 35, -23, 13, 26, 35, -18, -1, -15, -48, 8, 27, -19, 0, -1, 1, -35, 5, -22, -2, -45, -14, 8, 31, 27, -16, 35, 10, 0, 22, 26, -31, -14, 34, -18, 29, -8, 13, 44, -8, 11, 31, -26, -20, -24, -20, -35, -8, -34, -52, -26, 39, -31, 8, -24, 6, 45, -33, 4, -33, 4, 11, 28, 3, 19, -35, 35, -4, -29, 11, 30, -2, -34, 20, 20, -8, 15, 15, 19, -2, -15, 20, 7, -17, -30, -21, -9, 14, 52, 7, 24, -27, 35, -19, 5, 19, -40, -29, 23, 31, 21, -7, -44, -10, -10, 22, -17, 27, 27, -21, 15, 14, -14, 16, 61, -5, -3, 4, 29, -12, -38, -15, 10, -5, 39, 58, -19, -10, 9, 22, 15, 31, -9, -45, 25, 25, -26, -8, 30, 14, -24, 7, -27, 25, 37, -60, 42, 39, 49, -4, -6, -55, 19, -7, -6, -17, -13, -25, 49, 16, 9, 34, 34, 32, 32, -2, -13, -29, 5, -23, -8, -23, 49, 50, -50, 13, 13, -6, 3, 13, -18, -4, 40, 15, 3, -41, 34, 33, -26, -8, -34, -3, -3, 13, 32, 2, -9, -2, -53, 29, -43, 22, -26, -2, 64, 11, -13, 44, 40, 2, 1, -42, 40, -26, -16, -28, 16, -11, -22, 39, -24, -45, 18, -33, 11, 35, 4, -26, 23, -41, -34, 17, -5, 3, 1, 15, -31, 19, -52, -43, -23, -56, 26, 31, -17, -1, 12, 53, -10, -39, 73, -39, 68, -31, 24, -18, 28, -6, 11, -24, 2, -49, -6, -5, -32, 29, 8, 15, 28, 27, 21, 8, -9, -35, -36, 4, -3, 22, 42, 25, 17, -2, -35, 2, -32, 6, 27, 18, 11, 7, 33, 8, -33, -8, 34, -31, -2, 3, 46, -26, 23, -23, -9, -25, 40, -1, 15, -35, 11, 58, -48, -7, -36, -42, 9, 25, -11, 1, 6, 7, -29, 6, -22, -7, 31, 24, 8, 27, 8, -18, -30, 20, 12, -7, 12, -42, 30, 46, 15, 0, 14, 11, -5, -20, -8, 2, -25, -40, 5, 10, 25, 44, -24, 19, 4, -7, 23, 3, 26, -9, -2, 1, -3, -34, 17, 22, -29, -29, -14, 53, -27, 3, 46, -12, 7, -14, 30, 4, -38, 41, 13, -2, 7, 11, 39, -39, -19, 5, -40, 24, 0, -30, -56, -5, 22, 22, -53, 15, -5, -18, 20, -34, 15, 22, 9, 35, 3, 18, 44, -42, -17, -29, -26, -12, -61, -64, -37, -1, 13, -31, 32, 19, 29, -11, -30, -5, -49, 12, -26, 12, 0, -3, -44, 23, -38, 29, 45, -51, -14, 63, 16, 11, -29, 18, -20, -18, -31, -14, 0, 29, 3, 35, 34, -5, 7, 27, -33, 26, 14, 27, -28, -6, 31, 8, -3, -18, -39, 3, 48, -1, -36, -34, -33, 42, -19, 5, 19, 13, 57, 26, -5, -10, -21, -12, -11, 25, 11, -23, -10, -9, -14, -3, 16, -45, 43, 22, 12, -33, 14, 12, 25, 9, -22, -18, 35, 33, 20, 4, 22, 4, -14, -9, -14, -29, -53, 3, 17, 1, 12, -17, -51, -39, 51, 19, -32, 42, -35, 9, 40, -20, 48, 15, -38, -3, -18, 23, -64, -17, 51, 19, 4, 51, -35, -27, -10, -25, 15, -25, -68, -28, -42, -34, 18, 10, -23, -29, 26, 14, -5, -17, -23, 13, -27, -4, 28, -10, 9, 7, 35, -59, 20, -32, 17, 0, -60, -12, -24, -17, 33, -50, -9, 15, 18, 54, 19, -11, 19, 24, -32, -47, 1, -27, 40, -24, -36, 23, 14, 31, -28, 68, 9, -41, -13, 23, -72, 16, -17, -23, -13, 3, 61, -34, -12, 34, 26, -4, 7, 24, 21, -20, 12, -11, 66, -10, 38, 16, 22, 36, 15, 22, 5, 5, 16, 17, -31, -15, 1, 6, -30, 1, -2, 7, 8, -43, -9, -18, 40, -4, 49, -4, 32, -59, -19, -10, -51, -24, 15, -16, -5, -2, 35, 46, -23, 51, -18, -29, -31, -16, -19, 1, -2, 48, -2, -40, 41, -44, 26, -39, -73, 61, 24, 37, 60, 13, -39, -11, 7, 20, 7, 1, -19, -20, 18, 11, 33, -6, 19, 9, -10, -16, 4, 17, 39, 32, 13, -32, -31, -9, -12, 19, 8, 0, 15, -8, -55, -19, 22, 3, 9, 28, 37, 1, 5, -40, -11, -7, 25, 12, 23, -41, -6, 52, -4, -18, -18, 6, -36, 18, 3, -1, 48, -37, 7, 25, 27, -41, -11, 34, 31, -29, -34, 0, -35, 6, -12, 20, -28, 5, 9, -21, -8, -2, -32, -35, -31, -18, -11, -43, -25, 3, 23, -6, 14, 38, -4, -5, 39, -34, -19, -1, -1, 11, -12, 47, -4, 2, 18, 9, 17, -14, 14, -6, -1, -25, 42, -14, -50, 1, 29, -18, -23, 13, -9, 8, 42, -26, 36, 1, -28, -24, 25, 23, -3, -10, -27, 9, -25, -7, -22, 30, -46, -11, 9, 22, 27, 11, -36, 26, 17, -30, -68, 68, -25, 35, 21, 6, -10, -7, -45, -30, -4, 22, 6, -39, -2, 4, 52, 30, -61, -3, -5, -50, -28, 31, 23, 49, 34, 5, -19, -33, -35, 32, 3, 17, 2, -32, -33, 21, 19, 13, 44, -5, -22, 42, 22, -12, 13, 2, 39, 2, 1, -1, 19, -10, -42, -2, -12, 12, 13, -7, -42, -7, -6, 20, -36, -27, 19, 7, -11, -37, 54, -25, -27, -16, -8, 5, 9, -24, 16, 32, -23, -13, 29, -28, 18, 6, 15, 2, 28, -7, 30, -9, 19, -2, 2, -20, -7, 24, -36, -37, -43, -6, -30, 25, 14, 55, 30, -42, 28, -14, 12, -25, 27, -21, -39, 41, 6, -2, -56, 0, 27, -19, -6, 19, -17, 22, -17, 30, -24, -43, -20, -8, 24, -18, 10, 10, 5, -1, -38, 17, 12, -42, -26, -2, -25, -36, -52, 25, -8, -20, 34, 45, -37, 32, 9, -9, 32, -16, 13, -44, 22, 40, -34, -26, -12, -6, 40, -42, -28, -16, -27, 19, -7, 46, 32, -31, -24, -34, 36, 32, -22, 23, -47, 5, 47, -10, 0, -22, -43, -1, -3, -8, -18, 31, 21, -12, 38, -20, 25, -22, -7, 19, -6, 10, -16, -5, -19, 30, -1, 53, -8, -31, 3, -41, -29, -14, 25, -26, 26, 11, 14, 23, -22, 25, -17, -16, -11, -52, 24, 10, -1, -27, 18, 37, -19, -18, 26, 8, -46, -29, -22, 8, -18, 29, -13, -13, 17, -14, 23, 17, 19, -66, 6, 42, 27, -27, -25, -27, 23, -50, 31, 1, -9, 16, -19, -23, -39, 20, -51, -39, -18, -19, 26, 6, -57, 33, -19, 26, -8, 5, -16, -28, 34, -7, 0, -44, -22, 10, -24, -29, -16, -20, 15, -40, -20, 36, -1, 21, -14, -27, -54, -65, -22, 3, 51, 9, 21, -45, -18, -45, -19, 22, 41, 0, 51, -25, 2, -18, -22, -14, -53, -17, 2, -19, -7, -42, -37, -27, -39, 17, -16, 32, -47, -10, 37, 9, 38, -55, -26, 24, -13, 41, -8, 29, -3, -3, 8, -4, 5, 15, 46, -16, -43, -46, 13, 3, -38, 24, -13, -7, -18, 11, 30, -14, 41, 42, -10, 27, -1, -20, -1, 38, -5, 7, 1, 48, -5, 56, 13, -28, -2, -18, 5, -39, 13, 16, -51, 59, -10, 36, -18, -7, 38, 14, -33, -20, -22, 2, -2, -45, 36, -12, -7, 74, -6, 8, -28, -48, -13, 24, -17, -28, 9, -5, -12, -18, -25, -8, -12, -2, -7, 13, -5, 9, 12, 38, -32, -1, -3, -44, -29, 40, 46, 25, -1, 28, 9, -18, -21, -25, -4, -34, -1, 22, -7, -14, 30, -34, -36, -23, -23, -13, -7, -29, 7, -17, -23, -18, 28, 27, 17, 31, -58, 6, -20, -7, 4, -1, -2, -20, -1, 15, 40, -6, -20, -37, 26, -31, -7, 26, -37, -1, 30, -46, 15, -19, 12, 5, 5, 51, -8, -24, -30, 23, 39, -19, 24, -5, 41, -52, 12, 23, 29, -21, 13, 34, 20, 26, -26, 16, -27, 7, 15, 42, -22, -11, 9, -11, -7, -48, 24, -29, -18, 31, 19, -40, 4, -16, -21, 4, 0, 42, -20, -46, 16, 2, 2, -27, 16, 14, -11, -42, 11, 41, -12, -47, -41, 19, -12, 16, -14, -48, -27, -1, 3, 11, 31, -14, 23, -37, -34, -25, 24, 15, -33, -4, -30, -14, -11, 10, -45, -5, 22, -15, 39, -2, -5, 12, 28, 22, 2, -53, 12, -1, -23, -39, 45, -9, -29, -5, 15, -3, -25, 23, 7, -17, -21, 45, -56, -2, 12, -37, -15, -26, 12, 24, -29, 33, 14, 44, -78, 31, -19, 5, 37, 22, 8, -32, -4, 44, -27, 12, 5, 22, 35, -33, -8, -16, -27, -26, -3, 39, -16, 18, 30, 2, 0, 16, 51, -25, -23, -11, 18, 0, 55, 7, 31, -22, -60, -30, 47, -20, 3, -16, -11, -30, 24, -16, -58, -15, 7, -26, -21, 3, -31, -31, -24, 5, -17, -27, -17, 26, 33, 5, 8, -59, 39, -62, 0, 14, 28, 11, 23, -7, -34, 23, 10, 3, 7, 1, -31, 10, -30, -37, -51, -37, -14, -33, -18, 46, 17, 10, 11, -38, -7, -18, 22, 36, 31, -51, 16, 11, -19, 14, -49, -23, -16, -6, -6, -29, 55, 7, -11, -37, 11, -5, -46, 24, -17, 36, -60, 9, -29, 23, 33, 26, 10, 23, -39, -15, -23, -21, -5, -61, -5, -27, 0, 8, 41, 5, 6, 25, -34, -8, 32, -27, -32, 29, 22, 10, 18, -17, -14, 30, -41, -6, 5, 20, 31, -26, 11, -63, -14, -33, 20, 1, 19, 26, -5, 24, -10, -22, 6, 21, -22, -8, 18, -7, 19, 34, 38, -12, 23, 8, 18, -53, -6, -20, 0, 25, -44, -34, 0, 23, -16, 25, -29, -22, 9, -5, -22, 37, -16, -45, 52, -1, -24, -7, 34, -30, -18, -43, 37, -15, 10, 8, 14, -12, -4, 11, -58, -46, 16, -40, -21, -7, 13, -30, 23, 27, 3, 11, -18, -1, 11, 32, -12, -8, -44, -35, -50, -11, -13, -11, -13, -24, -13, 40, 35, -36, 73, 30, -7, 8, -6, 15, -16, -46, -31, -23, -6, 56, -29, 3, 35, 29, 19, -14, 21, -24, 16, 2, 48, 1, 45, 15, 6, 16, -25, -60, 32, -39, 9, 16, 26, 10, -2, -40, -10, -22, 27, -14, 8, -2, 15, -8, -5, -19, 11, 27, -9, 47, -24, 6, -8, -27, 23, -7, 12, 59, -11, -6, -19, -9, 27, -2, -18, 14, 29, -15, -27, 23, -45, 1, -29, -9, -29, -19, -23, -15, -7, -24, -26, 27, -58, -23, 19, -1, -43, 10, -32, 21, 9, -48, 22, -14, 4, 30, 17, 25, 20, -2, -13, 40, -30, 9, 3, 31, -18, -7, 28, 32, -30, -1, -5, -37, 29, -39, 11, -44, -36, -31, -22, 25, 22, -20, 14, -32, -6, 0, -12, 15, -35, -18, -9, 41, -30, 35, 28, -12, 5, 18, -29, 10, -8, -6, -3, 17, -4, 3, -58, -30, -6, 13, 13, -25, 32, -19, -24, -38, 2, -27, 2, -24, -6, 18, 16, -38, -3, 27, 28, -33, -10, 51, -14, -44, 40, -11, 16, 2, -11, -5, 36, -11, 11, 5, 6, -24, -12, 41, -25, -20, -50, 14, -21, 7, -12, 23, -28, 4, 28, 40, 6, 27, -21, -45, -34, 16, 2, 30, 26, -22, -4, -25, 39, -43, -15, 13, 0, 24, -12, 14, 12, -2, -10, 7, -18, 23, 43, -41, -25, 4, -13, -4, -49, -11, -39, -25, -30, 43, 16, 10, -33, 14, 19, -10, 27, 17, 8, 10, 20, -27, 39, -16, 28, 39, -18, 18, -33, -40, -6, 24, 26, -17, 42, -21, 24, -29, -40, -17, -31, 15, 54, 3, -8, -20, -26, -48, 19, -15, -9, 23, 36, 2, -10, -7, 16, -40, 16, 9, 17, -23, 42, 33, 36, 20, -29, 32, -39, -16, 23, 3, 5, 15, -36, 10, 26, -8, -2, 25, 31, 16, -25, -3, -22, 16, 41, -25, 12, -33, 34, -16, 30, -1, 1, -30, 4, -22, -6, 23, 13, 3, 9, 19, 4, -8, -23, -31, 18, 42, 9, -27, 49, -45, 8, -7, -40, 6, -6, -27, -16, 32, -16, -1, -15, -5, 39, 33, -7, -16, -20, -46, 12, -27, 6, -23, 14, -12, 17, 1, 2, -4, 14, -23, 25, 25, -3, 16, -11, 30, 20, -36, -11, 6, -35, 15, 18, -7, 3, 7, 17, -58, 31, 26, 18, -18, 25, -29, 21, -44, 8, 25, 23, 35, 20, -31, -16, -15, 4, 19, -12, -16, -21, 34, -10, -11, 33, 27, 9, -64, -21, -37, 13, -5, -33, 7, 3, -13, -45, -9, -6, 12, 5, -41, -10, -1, 18, 31, -47, -5, -18, -8, -13, 24, 5, 12, 38, -1, -33, 28, 49, -30, -11, -4, -19, 19, -7, 22, -15, -8, 22, -42, -16, 48, -59, 12, 8, -17, -47, -35, -15, 7, 4, 8, 29, 5, 4, -5, -30, 19, -39, 9, -27, 8, -33, 17, 2, 42, -8, -47, 5, 3, 11, 31, -30, -8, 2, 32, -21, -14, 27, 0, -25, -1, 16, 12, -6, -49, 55, -4, 0, -11, 50, 32, 0, -57, -16, -3, -34, -43, -23, -33, 25, 7, -32, 1, 63, 21, -24, -11, 53, -4, -10, -43, 14, -20, 44, 5, -23, 8, -13, 4, 18, -9, -8, 15, -10, 0, 54, 15, -40, 24, 31, 28, 4, 1, 2, -20, 16, -35, 31, -12, -5, 37, 10, -25, 35, -24, 38, -30, 8, -14, 4, 7, -29, 40, 1, -13, 40, -28, 6, -3, -11, 43, 49, 61, -2, 25, 21, 16, 20, -1, 17, -50, 4, -27, 15, 34, -37, 7, -23, -8, -43, -14, -49, -25, -2, -39, 13, 6, -39, -28, -1, -34, -9, 48, -15, -27, 18, -8, -17, -10, 16, 36, -9, 21, -14, -22, 6, -13, 26, -35, -48, 6, -12, 34, -5, 5, -18, 3, 5, -11, -26, 6, -41, 26, -36, 21, 17, -38, -1, 41, -28, 31, 7, 8, 27, 9, 8, -40, 23, -4, -36, -61, 24, 21, 17, 26, 26, -32, 28, 29, -15, -30, -30, -32, -13, -30, 30, 10, -30, -35, 9, -19, -39, 31, 7, 11, 30, 57, 24, -21, -45, -29, -1, -4, -41, 7, -2, -3, 5, 34, 25, -20, 32, -13, -7, -2, 26, -41, 9, 2, -33, 21, -7, 37, -10, 49, 2, -26, -13, -11, -26, -38, -48, 29, -26, -6, -28, -20, 12, -31, 10, 6, -11, -38, -23, 13, 18, 21, 18, 5, -20, 27, -29, 0, 28, 3, -25, -16, -34, 30, 28, -12, -20, -24, -25, 45, -15, 19, 54, -23, 32, -27, 52, 28, 0, -4, 16, 11, -4, 19, 7, 53, 15, 21, 18, -24, -27, 0, -19, -19, 32, -12, 35, -8, -34, -22, 20, 26, 31, 35, 5, 30, 16, 3, -17, 2, 30, -25, -1, -2, 40, -26, -15, 19, -20, 5, 7, 9, 24, -7, 38, -30, -10, -14, -16, -10, -14, 9, -28, -7, 33, -5, 21, -30, -1, -19, -2, -3, -36, -9, -35, -16, 12, 25, -73, 40, 39, -35, 3, -14, -2, 8, 19, -55, 4, 8, -3, -23, -41, 46, 18, 39, 25, 37, -12, -18, 38, 41, -29, -15, -14, 16, -21, 23, -24, -47, -9, 28, -15, -23, -2, -10, -10, -11, 31, 1, 28, -48, 10, -25, -33, 33, 6, 18, -13, 5, 38, -26, 12, 25, -17, -27, -28, 30, -19, 9, -13, 34, -31, 0, -13, 8, 22, 34, -25, 25, 21, 25, 1, -26, 42, -36, -57, 13, -23, -10, 3, -47, -19, -47, -30, -5, 35, 21, -4, 37, 21, -20, 6, -11, 35, 12, 2, 21, 43, -16, -41, 4, -33, -14, -1, -5, -14, 18, -19, -10, -14, -53, 45, -2, 23, -25, 5, 24, 9, 33, 32, 21, -20, -18, 30, 32, -14, -8, 16, 16, -3, 10, -7, -15, 21, 0, 19, -33, -3, -2, -6, 1, -28, 27, -3, 18, -20, 16, 29, 9, -6, -13, 19, 20, -7, -10, -23, -8, -8, -12, 7, 21, -28, 1, -20, 14, 26, 10, 28, -5, 2, -12, 0, 17, 12, 7, 10, 2, -18, 34, -13, -20, 42, 16, 27, -19, -39, -12, 16, -19, 38, 15, 8, 22, -40, 22, -8, 37, -11, 15, 36, -43, 0, 24, -35, -20, 48, -21, 6, 33, -6, -19, -12, 11, -10, -16, -19, 31, 20, -44, -26, 17, -12, -19, -2, -57, 12, 23, -46, -36, 6, 21, 22, 1, 7, 39, -13, 30, 6, 35, 0, -3, 8, 17, 16, 26, -20, 12, 12, 28, 16, 33, -30, 41, -12, -24, -5, 32, 21, 37, -6, -18, -48, -13, 34, 29, -8, 23, -27, 23, 39, -11, 8, 11, 6, -36, 27, -20, 1, -1, -11, 19, -20, -9, 35, -11, 20, -27, 22, -30, -19, 31, -27, -31, 22, 14, 11, -18, -26, -27, -21, -4, -43, -28, -12, 24, 40, -19, 13, -27, -37, -25, -16, 14, -27, -15, -9, 37, -7, 38, -8, 2, -10, -19, 45, 0, -10, -31, 38, -52, -6, -38, -14, 10, -47, -4, -9, 16, 4, -22, 47, 38, -5, -12, 35, 12, -15, -29, 54, 18, 4, -20, -20, 14, -8, 55, 30, -34, -32, 62, -49, -2, 11, -5, -70, 36, -38, 44, -19, 24, 19, -25, -23, 5, 38, 27, -39, -26, 8, -9, -20, -14, -7, 15, -2, 18, -10, -37, -30, -3, -22, -30, -7, -3, 2, 29, -6, -8, -2, -27, 31, 25, 9, -10, -18, -3, -13, 22, 10, 7, 3, -58, -26, -5, 8, -19, -37, 32, 35, 36, -13, -30, 20, 13, -5, 22, -6, 6, 37, 35, 11, 3, -57, 18, 8, 60, -7, -2, -6, 16, 16, 23, -12, 6, -32, 40, 32, -26, -5, -18, 34, 3, 26, -6, 22, 5, 23, 45, 51, 14, 33, -25, -45, 27, -1, 29, } +#define IP3_BIAS {5, 62, -6, 46, 5, -1, -23, -38, 3, 85, 41, -43, 52, 90, -13, 21, 1, 52, 51, -11, 10, 41, -48, -3, 16, 16, 30, -49, -1, 0, 33, 12, 1, -44, -10, 7, -54, 52, -35, 69, -52, 80, 96, -6, 19, -56, 68, -5, -32, 63, 8, -44, 37, 12, -49, 45, 41, 38, 53, -47, 16, 35, -63, 72, -17, 1, 38, -17, 0, 11, -5, -20, 92, 63, -18, 111, -56, 23, 26, -49, -40, 90, 49, 55, 36, -44, 29, -38, -32, -22, 13, -29, -27, 9, 65, 58, 91, -63, -67, 5, -9, -29, 43, 40, 29, -27, 60, 35, 19, -20, 93, 5, 28, -28, -44, -12, -32, -23, 5, 3, -43, 8, 112, 0, -5, 13, -14, -27, -8, -15, 81, -55, -17, 0, -36, 79, 22, 25, 15, 2, 15, 43, -6, 45, } +#define IP4_WT {-7, 25, -1, 9, 25, -40, -58, 8, -3, 8, 8, -32, 17, 24, 8, -25, 2, 10, 17, -24, -27, 9, -1, -18, -12, -8, -26, 0, -30, -20, 4, -25, -43, -33, -42, 11, -29, -39, 0, -50, -22, 20, 32, -19, 31, -38, 26, -4, 3, 10, 9, -46, -4, -38, -30, 13, 17, 14, -8, 5, -13, -5, -46, 34, -4, -1, -19, 14, -15, -51, -44, -44, 31, 23, -21, 8, -20, 8, -14, 8, -36, 22, -36, -18, 3, -37, -5, -22, -16, -4, -17, -31, 5, -41, 12, 19, 30, -70, -31, -15, -39, -43, 2, -3, 14, -45, -26, 2, 22, -25, 38, 1, -13, -11, -23, -10, -13, 4, -20, -47, -7, -4, 29, -12, -8, -28, -32, -42, -20, -5, 28, 4, 14, 10, -18, 5, -37, 7, 10, -6, -18, 2, -10, -3, 20, 17, -4, -13, 20, -20, 20, -6, 23, -23, 13, 8, -3, -7, 15, 4, -4, 26, -24, 8, -6, -8, 23, 3, 3, 29, -20, 24, -26, 19, 4, -36, 14, 36, 2, 10, 9, 13, 23, -14, -9, 12, 13, -22, 7, -3, 7, -9, 11, -13, 2, 16, -18, -8, 7, 5, -2, 13, -24, -21, -17, 11, 25, 4, 22, 19, -6, 28, 11, -25, -7, -16, -4, 13, 10, -8, -3, 15, 17, 4, 16, -7, 28, 25, -8, 15, -18, -22, 6, -7, 20, 0, 16, -12, -24, 21, -10, 12, 9, 3, -6, 15, -11, -4, -4, -4, 3, -14, 30, 8, 1, -6, -4, -8, 15, -11, 32, -7, 5, 12, -16, -8, -32, -7, 9, 6, -6, -3, -22, 7, 4, 38, -8, 15, 36, -10, -13, 14, 23, -13, 13, -12, -10, 12, 17, 4, -32, -12, -26, -32, 30, 9, 22, -12, -20, 8, 22, -8, 32, 5, 8, 16, -19, -41, 28, 16, 5, -2, -15, -11, 24, -19, 24, 21, -22, 8, -18, 9, 31, -12, -2, -29, 36, -35, 17, -11, -20, -2, -4, -8, -26, 27, -6, -13, 15, 1, -17, -13, 8, 5, -29, 21, 5, 15, 14, -14, -25, -21, -8, -9, -15, -8, 15, -15, -18, 5, 35, 18, 3, -8, 21, -18, -21, -24, -16, -26, -29, -28, -19, -16, 18, -14, -34, 11, -9, 2, -15, 24, 0, 11, -31, 4, -3, -29, -23, -24, 10, -13, 4, 0, -10, -39, 27, 18, 12, 8, -11, -2, 1, -28, 17, 2, 13, -8, -9, -14, -5, -18, 33, 19, -6, 1, 25, 16, -12, 17, -5, -29, 16, -17, 8, -5, 19, 20, -2, -7, -19, -22, -9, 5, -14, -18, -21, 6, -10, -29, 29, -16, -5, 31, 11, -7, -19, 0, 20, 6, -2, -15, -1, -9, -15, -4, -13, -17, -4, -17, -15, 0, -15, 3, -1, -7, 8, -16, -28, 24, 1, 26, 5, -19, -13, -1, -18, 0, 8, 26, 13, 18, 5, 23, 21, 4, -27, 18, -1, 24, -12, 15, 6, -15, -19, -1, -3, -24, 24, -17, -6, 23, -5, -10, 7, -16, 25, -15, -16, 26, 17, -19, -7, -8, 9, -11, -7, -12, 5, 17, -30, 0, -34, 12, 0, 25, -18, 4, -22, 5, -7, -4, -22, -16, 14, 32, -24, -13, 10, -21, 14, 13, 16, 21, -19, -30, -13, -19, 3, -26, -20, 27, -22, 14, -5, 8, -28, -29, 28, 21, -16, -11, -9, -23, 6, -1, -27, -41, -2, -18, 27, -11, -10, 22, -14, 19, 12, -19, -28, -1, -2, -6, -18, -14, 23, 8, -14, -25, -20, -19, 24, 13, -16, 14, 24, -23, -12, 24, 30, -9, 25, -23, 5, -14, -13, -11, 4, 14, -9, -12, -18, 10, -3, -27, 7, -34, -7, 14, 20, 9, 0, 8, 13, 9, -23, 17, -4, -11, 11, 28, -22, -24, 2, -15, 8, -26, -35, -22, -24, -10, -4, -32, 12, 24, 5, 21, 6, -8, -17, -3, -3, -9, 24, -17, 15, 5, -2, 28, -23, 15, 2, 5, -4, 12, 17, 30, 3, 14, -19, -21, -14, -10, -7, 2, -20, 16, 17, 29, 8, 11, 12, -21, -37, -5, -20, -2, 26, -28, 8, 5, 19, 28, -27, 12, -27, -24, -7, 32, -7, 14, -34, -22, -5, -27, 25, -31, -17, -1, 22, 18, -26, -21, 2, -20, 20, 25, 5, 10, -19, -15, 11, 2, 0, 25, -11, 9, 24, -11, -24, -9, 30, 16, -10, -11, 8, 25, 29, -28, -12, -9, 7, -4, -10, 10, -17, 3, -6, 6, -27, 9, 15, -26, 15, -5, -36, 25, -14, -13, 3, 34, -23, 4, -34, 9, 12, -13, 27, 23, 10, 16, -22, 3, 20, 19, -13, 5, -4, 2, -25, -5, 23, -29, 4, 12, -37, 12, -44, -32, -3, -32, -4, 21, -16, 5, 5, 10, -1, 17, 21, -30, -10, -37, -15, -23, 2, 7, 9, -7, -12, 28, -11, 3, -14, 20, -39, 22, 9, 5, -29, 8, -16, 19, 19, 35, 12, 16, 37, -5, 1, 4, -24, 23, -4, -14, -25, -17, 28, 14, -4, -23, -21, -24, -14, 9, -22, 12, -16, 8, 25, 4, 0, 18, -10, -30, -9, -3, -2, 14, -31, 8, -1, 17, -17, 7, 14, 12, -27, -23, -24, -6, -1, 22, -4, -7, -27, -23, -5, 16, 24, -11, -14, 16, -7, 4, 22, 7, -6, -25, -12, -20, 36, 10, 23, 7, 20, 21, -15, -14, 30, 2, 23, 11, 12, -25, 24, -24, -2, 16, -1, 9, -17, -2, -9, 8, 16, 1, 6, 13, 4, -20, -27, 8, 26, 3, -10, 1, 16, -27, 13, -10, -17, 5, 3, 22, 1, -32, -5, 5, 8, -30, -8, -6, 15, -11, -15, -1, 7, -26, 0, -2, 13, -22, 4, -5, 9, -23, 9, 28, 21, 7, -11, -15, -8, -21, 17, -21, 24, -21, -18, 26, -16, -35, 16, 11, -19, -19, -31, 20, 4, -11, -13, -4, -22, -3, 24, -6, 5, 5, 27, 2, 4, -15, 14, -11, 18, 13, -2, 6, 9, -8, 30, 4, -8, -9, -12, 4, -13, -38, -30, -23, 39, 14, 11, -22, 10, 4, 14, -14, 3, -12, 7, -17, -26, 31, -21, 16, -19, 4, -10, -22, -36, 40, -20, 42, -12, -7, 15, -6, 13, 1, 16, -5, -17, -26, 26, 26, -16, 4, 5, -14, 19, 14, 3, 13, 13, -13, -4, -13, 12, 24, 13, 12, 12, -28, -25, 6, 8, -7, -26, 29, 5, -23, 24, -23, 28, 16, -18, 19, -12, -17, -4, -15, -28, -36, -37, 31, 10, -23, 0, 12, 26, 20, -10, 24, 20, 20, 7, -14, 30, -28, -2, -2, -19, 2, 17, -31, 11, 27, -22, 11, -21, -23, -45, 19, 24, 8, 17, 22, 0, 9, 25, -4, 12, 5, 21, -17, 12, 5, -15, 8, 0, 10, 10, -12, 4, -4, 4, -8, 17, 9, 15, 22, -10, 1, 27, 23, -21, -23, -31, -16, 18, -35, -24, -20, 4, 18, -7, -9, 11, 27, 5, 34, 9, 1, -30, -24, -24, -10, 24, -25, -1, 12, -25, 5, -10, -16, -17, 14, -17, 9, -25, 2, 18, -19, -10, 1, -5, 27, -4, 2, -37, 25, -5, -13, -9, -9, 21, -19, -17, -13, 20, -9, 8, 13, -11, 21, 11, 14, 3, -20, 13, 12, -26, 34, 14, -8, 6, 17, -15, 26, 15, -15, -19, 10, 18, -33, 18, 0, -13, 10, 3, -25, 24, 14, -3, -3, 21, 11, -29, -9, 30, 12, 24, 8, -7, -39, -30, 22, -10, -16, 3, 26, -14, 10, -20, -23, -17, -6, -4, 12, -2, -24, 18, -9, 17, 19, 16, -23, 0, 9, 28, -14, 11, -8, 6, -16, -17, 19, -36, -26, 1, -8, -24, 37, -7, 18, 10, 20, 2, -23, -21, 7, 26, 19, -19, -1, -27, 0, 2, -1, -2, -8, -19, -7, 3, 7, 7, -15, -24, -34, -20, -11, 18, -19, 18, -2, -6, 1, 13, -28, -11, -21, -3, 11, 16, -8, 21, 4, 7, 9, 5, -9, 8, -28, -8, -15, 8, 20, -5, -3, -13, 3, -16, -3, 21, -1, 26, -2, -16, -17, -24, -22, 21, -18, 28, 16, -33, -22, -6, 9, -16, 2, 4, -1, -8, -10, 12, -10, -6, -15, 5, -17, 18, -28, -10, 15, 10, 22, -44, -23, 19, 28, 1, -23, 13, 3, 9, 21, 7, -23, 11, -1, -22, 15, -6, 10, 18, 13, 6, -13, -24, -23, -41, 7, -37, 0, -9, 15, -24, 4, 20, -3, -5, 0, 23, -7, 25, -7, -2, 8, 9, -10, 6, 12, -6, -9, -23, 22, -9, -13, -5, -4, -19, -17, 0, 15, 28, -18, 8, -9, 18, 1, -12, -3, -8, 20, 0, 20, -7, 7, -23, -23, -4, -13, 13, 22, -14, 1, 12, -29, -5, 22, 18, -19, -14, -8, -2, 7, 2, -6, -4, -1, -29, 2, 15, -6, 27, -23, 19, -7, -15, 10, -22, -23, -18, -20, 16, -12, -19, 3, -18, -5, 14, 13, -5, 16, 0, -29, 19, 23, -7, 0, 23, 23, -31, 31, -18, -18, 16, 6, 13, 13, -8, -23, -16, -15, -19, -18, 26, 1, -9, -19, -16, -13, -31, 0, 11, -20, -11, -21, 10, 18, 10, -32, 13, -16, -10, 14, 2, 16, 12, 21, 33, -15, 27, -27, -9, -32, -17, 9, 23, 19, -32, -26, 19, 21, 6, 23, -18, -32, -15, 11, 8, -21, -50, 5, 26, -14, -19, -32, -1, -7, 18, -20, -21, -16, 22, -11, -1, -23, -24, -6, 24, 8, 9, 17, -31, 3, 2, -15, 0, -27, 23, -39, -16, 22, -8, -30, 13, 28, 25, -19, 20, 0, 29, -27, 4, -24, -4, -18, -25, -1, 10, 19, 17, -13, 10, -2, 10, 7, -4, -2, -1, 16, -11, -19, 0, 15, 1, 6, 0, -6, -16, 17, -9, 28, 23, 16, -4, 24, 23, 24, 16, 15, -9, 1, -25, 10, -26, 3, 18, -30, -16, -18, 4, 3, -10, -19, 27, -24, -16, 20, -15, -15, -20, -8, -21, 18, -14, -20, 15, 5, 3, -14, -9, -3, 20, -6, -31, 18, -21, -3, 31, 0, 7, 13, 1, 26, 14, -20, 2, -3, -13, -13, 13, -16, 10, -18, -14, -22, -12, -14, -3, 6, -17, 11, -5, 20, -26, -15, 27, 17, -1, 11, -24, -6, -23, -15, -10, -7, -2, 16, 3, -11, -9, 15, 0, 13, } +#define IP4_BIAS {95, -49, 1, 30, -12, 23, -20, 12, 1, -51, -13, 3, } diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn.cpp b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6e871cc0ba89987e8c8b53a191e170dc413c253 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "ds_cnn.h" + +const q7_t DS_CNN::conv1_wt[CONV1_OUT_CH*CONV1_KX*CONV1_KY]=CONV1_WT; +const q7_t DS_CNN::conv1_bias[CONV1_OUT_CH]=CONV1_BIAS; +const q7_t DS_CNN::conv2_ds_wt[CONV1_OUT_CH*CONV2_DS_KX*CONV2_DS_KY]=CONV2_DS_WT; +const q7_t DS_CNN::conv2_ds_bias[CONV1_OUT_CH]=CONV2_DS_BIAS; +const q7_t DS_CNN::conv2_pw_wt[CONV2_OUT_CH*CONV1_OUT_CH]=CONV2_PW_WT; +const q7_t DS_CNN::conv2_pw_bias[CONV2_OUT_CH]=CONV2_PW_BIAS; +const q7_t DS_CNN::conv3_ds_wt[CONV2_OUT_CH*CONV3_DS_KX*CONV3_DS_KY]=CONV3_DS_WT; +const q7_t DS_CNN::conv3_ds_bias[CONV2_OUT_CH]=CONV3_DS_BIAS; +const q7_t DS_CNN::conv3_pw_wt[CONV3_OUT_CH*CONV2_OUT_CH]=CONV3_PW_WT; +const q7_t DS_CNN::conv3_pw_bias[CONV3_OUT_CH]=CONV3_PW_BIAS; +const q7_t DS_CNN::conv4_ds_wt[CONV3_OUT_CH*CONV4_DS_KX*CONV4_DS_KY]=CONV4_DS_WT; +const q7_t DS_CNN::conv4_ds_bias[CONV3_OUT_CH]=CONV4_DS_BIAS; +const q7_t DS_CNN::conv4_pw_wt[CONV4_OUT_CH*CONV3_OUT_CH]=CONV4_PW_WT; +const q7_t DS_CNN::conv4_pw_bias[CONV4_OUT_CH]=CONV4_PW_BIAS; +const q7_t DS_CNN::conv5_ds_wt[CONV4_OUT_CH*CONV5_DS_KX*CONV5_DS_KY]=CONV5_DS_WT; +const q7_t DS_CNN::conv5_ds_bias[CONV4_OUT_CH]=CONV5_DS_BIAS; +const q7_t DS_CNN::conv5_pw_wt[CONV5_OUT_CH*CONV4_OUT_CH]=CONV5_PW_WT; +const q7_t DS_CNN::conv5_pw_bias[CONV5_OUT_CH]=CONV5_PW_BIAS; +const q7_t DS_CNN::final_fc_wt[CONV5_OUT_CH*OUT_DIM]=FINAL_FC_WT; +const q7_t DS_CNN::final_fc_bias[OUT_DIM]=FINAL_FC_BIAS; + +DS_CNN::DS_CNN() +{ + scratch_pad = new q7_t[SCRATCH_BUFFER_SIZE]; + buffer1 = scratch_pad; + buffer2 = buffer1 + (CONV1_OUT_CH*CONV1_OUT_X*CONV1_OUT_Y); + col_buffer = buffer2 + (CONV2_OUT_CH*CONV2_OUT_X*CONV2_OUT_Y); + frame_len = FRAME_LEN; + frame_shift = FRAME_SHIFT; + num_mfcc_features = NUM_MFCC_COEFFS; + num_frames = NUM_FRAMES; + num_out_classes = OUT_DIM; + in_dec_bits = MFCC_DEC_BITS; +} + +DS_CNN::~DS_CNN() +{ + delete scratch_pad; +} + +void DS_CNN::run_nn(q7_t* in_data, q7_t* out_data) +{ + //CONV1 : regular convolution + arm_convolve_HWC_q7_basic_nonsquare(in_data, CONV1_IN_X, CONV1_IN_Y, 1, conv1_wt, CONV1_OUT_CH, CONV1_KX, CONV1_KY, CONV1_PX, CONV1_PY, CONV1_SX, CONV1_SY, conv1_bias, CONV1_BIAS_LSHIFT, CONV1_OUT_RSHIFT, buffer1, CONV1_OUT_X, CONV1_OUT_Y, (q15_t*)col_buffer, NULL); + arm_relu_q7(buffer1,CONV1_OUT_X*CONV1_OUT_Y*CONV1_OUT_CH); + + //CONV2 : DS + PW conv + //Depthwise separable conv (batch norm params folded into conv wts/bias) + arm_depthwise_separable_conv_HWC_q7_nonsquare(buffer1,CONV2_IN_X,CONV2_IN_Y,CONV1_OUT_CH,conv2_ds_wt,CONV1_OUT_CH,CONV2_DS_KX,CONV2_DS_KY,CONV2_DS_PX,CONV2_DS_PY,CONV2_DS_SX,CONV2_DS_SY,conv2_ds_bias,CONV2_DS_BIAS_LSHIFT,CONV2_DS_OUT_RSHIFT,buffer2,CONV2_OUT_X,CONV2_OUT_Y,(q15_t*)col_buffer, NULL); + arm_relu_q7(buffer2,CONV2_OUT_X*CONV2_OUT_Y*CONV2_OUT_CH); + + //Pointwise conv + arm_convolve_1x1_HWC_q7_fast_nonsquare(buffer2, CONV2_OUT_X, CONV2_OUT_Y, CONV1_OUT_CH, conv2_pw_wt, CONV2_OUT_CH, 1, 1, 0, 0, 1, 1, conv2_pw_bias, CONV2_PW_BIAS_LSHIFT, CONV2_PW_OUT_RSHIFT, buffer1, CONV2_OUT_X, CONV2_OUT_Y, (q15_t*)col_buffer, NULL); + arm_relu_q7(buffer1,CONV2_OUT_X*CONV2_OUT_Y*CONV2_OUT_CH); + + //CONV3 : DS + PW conv + //Depthwise separable conv (batch norm params folded into conv wts/bias) + arm_depthwise_separable_conv_HWC_q7_nonsquare(buffer1,CONV3_IN_X,CONV3_IN_Y,CONV2_OUT_CH,conv3_ds_wt,CONV2_OUT_CH,CONV3_DS_KX,CONV3_DS_KY,CONV3_DS_PX,CONV3_DS_PY,CONV3_DS_SX,CONV3_DS_SY,conv3_ds_bias,CONV3_DS_BIAS_LSHIFT,CONV3_DS_OUT_RSHIFT,buffer2,CONV3_OUT_X,CONV3_OUT_Y,(q15_t*)col_buffer, NULL); + arm_relu_q7(buffer2,CONV3_OUT_X*CONV3_OUT_Y*CONV3_OUT_CH); + //Pointwise conv + arm_convolve_1x1_HWC_q7_fast_nonsquare(buffer2, CONV3_OUT_X, CONV3_OUT_Y, CONV2_OUT_CH, conv3_pw_wt, CONV3_OUT_CH, 1, 1, 0, 0, 1, 1, conv3_pw_bias, CONV3_PW_BIAS_LSHIFT, CONV3_PW_OUT_RSHIFT, buffer1, CONV3_OUT_X, CONV3_OUT_Y, (q15_t*)col_buffer, NULL); + arm_relu_q7(buffer1,CONV3_OUT_X*CONV3_OUT_Y*CONV3_OUT_CH); + + //CONV4 : DS + PW conv + //Depthwise separable conv (batch norm params folded into conv wts/bias) + arm_depthwise_separable_conv_HWC_q7_nonsquare(buffer1,CONV4_IN_X,CONV4_IN_Y,CONV3_OUT_CH,conv4_ds_wt,CONV3_OUT_CH,CONV4_DS_KX,CONV4_DS_KY,CONV4_DS_PX,CONV4_DS_PY,CONV4_DS_SX,CONV4_DS_SY,conv4_ds_bias,CONV4_DS_BIAS_LSHIFT,CONV4_DS_OUT_RSHIFT,buffer2,CONV4_OUT_X,CONV4_OUT_Y,(q15_t*)col_buffer, NULL); + arm_relu_q7(buffer2,CONV4_OUT_X*CONV4_OUT_Y*CONV4_OUT_CH); + //Pointwise conv + arm_convolve_1x1_HWC_q7_fast_nonsquare(buffer2, CONV4_OUT_X, CONV4_OUT_Y, CONV3_OUT_CH, conv4_pw_wt, CONV4_OUT_CH, 1, 1, 0, 0, 1, 1, conv4_pw_bias, CONV4_PW_BIAS_LSHIFT, CONV4_PW_OUT_RSHIFT, buffer1, CONV4_OUT_X, CONV4_OUT_Y, (q15_t*)col_buffer, NULL); + arm_relu_q7(buffer1,CONV4_OUT_X*CONV4_OUT_Y*CONV4_OUT_CH); + + //CONV5 : DS + PW conv + //Depthwise separable conv (batch norm params folded into conv wts/bias) + arm_depthwise_separable_conv_HWC_q7_nonsquare(buffer1,CONV5_IN_X,CONV5_IN_Y,CONV4_OUT_CH,conv5_ds_wt,CONV4_OUT_CH,CONV5_DS_KX,CONV5_DS_KY,CONV5_DS_PX,CONV5_DS_PY,CONV5_DS_SX,CONV5_DS_SY,conv5_ds_bias,CONV5_DS_BIAS_LSHIFT,CONV5_DS_OUT_RSHIFT,buffer2,CONV5_OUT_X,CONV5_OUT_Y,(q15_t*)col_buffer, NULL); + arm_relu_q7(buffer2,CONV5_OUT_X*CONV5_OUT_Y*CONV5_OUT_CH); + //Pointwise conv + arm_convolve_1x1_HWC_q7_fast_nonsquare(buffer2, CONV5_OUT_X, CONV5_OUT_Y, CONV4_OUT_CH, conv5_pw_wt, CONV5_OUT_CH, 1, 1, 0, 0, 1, 1, conv5_pw_bias, CONV5_PW_BIAS_LSHIFT, CONV5_PW_OUT_RSHIFT, buffer1, CONV5_OUT_X, CONV5_OUT_Y, (q15_t*)col_buffer, NULL); + arm_relu_q7(buffer1,CONV5_OUT_X*CONV5_OUT_Y*CONV5_OUT_CH); + + //Average pool + arm_avepool_q7_HWC_nonsquare (buffer1,CONV5_OUT_X,CONV5_OUT_Y,CONV5_OUT_CH,CONV5_OUT_X,CONV5_OUT_Y,0,0,1,1,1,1,NULL,buffer2, 2); + + arm_fully_connected_q7(buffer2, final_fc_wt, CONV5_OUT_CH, OUT_DIM, FINAL_FC_BIAS_LSHIFT, FINAL_FC_OUT_RSHIFT, final_fc_bias, out_data, (q15_t*)col_buffer); + +} + + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn.h new file mode 100644 index 0000000000000000000000000000000000000000..fe8dafe6e4f63eb3893fc54eb8f3a4a8c756a7fe --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __DS_CNN_H__ +#define __DS_CNN_H__ + +#include "nn.h" +#include "ds_cnn_weights.h" +#include "local_NN.h" +#include "arm_math.h" + +#define SAMP_FREQ 16000 +#define MFCC_DEC_BITS 1 +#define FRAME_SHIFT_MS 20 +#define FRAME_SHIFT ((int16_t)(SAMP_FREQ * 0.001 * FRAME_SHIFT_MS)) +#define NUM_FRAMES 49 +#define NUM_MFCC_COEFFS 10 +#define MFCC_BUFFER_SIZE (NUM_FRAMES*NUM_MFCC_COEFFS) +#define FRAME_LEN_MS 40 +#define FRAME_LEN ((int16_t)(SAMP_FREQ * 0.001 * FRAME_LEN_MS)) + +#define IN_DIM (NUM_FRAMES*NUM_MFCC_COEFFS) +#define OUT_DIM 12 + +#define CONV1_OUT_CH 64 +#define CONV1_IN_X NUM_MFCC_COEFFS +#define CONV1_IN_Y NUM_FRAMES +#define CONV1_KX 4 +#define CONV1_KY 10 +#define CONV1_SX 2 +#define CONV1_SY 2 +#define CONV1_PX 1 +#define CONV1_PY 4 +#define CONV1_OUT_X 5 +#define CONV1_OUT_Y 25 +#define CONV1_BIAS_LSHIFT 2 +#define CONV1_OUT_RSHIFT 6 + +#define CONV2_OUT_CH 64 +#define CONV2_IN_X CONV1_OUT_X +#define CONV2_IN_Y CONV1_OUT_Y +#define CONV2_DS_KX 3 +#define CONV2_DS_KY 3 +#define CONV2_DS_SX 1 +#define CONV2_DS_SY 1 +#define CONV2_DS_PX 1 +#define CONV2_DS_PY 1 +#define CONV2_OUT_X 5 +#define CONV2_OUT_Y 25 +#define CONV2_DS_BIAS_LSHIFT 2 +#define CONV2_DS_OUT_RSHIFT 5 +#define CONV2_PW_BIAS_LSHIFT 4 +#define CONV2_PW_OUT_RSHIFT 8 + +#define CONV3_OUT_CH 64 +#define CONV3_IN_X CONV2_OUT_X +#define CONV3_IN_Y CONV2_OUT_Y +#define CONV3_DS_KX 3 +#define CONV3_DS_KY 3 +#define CONV3_DS_SX 1 +#define CONV3_DS_SY 1 +#define CONV3_DS_PX 1 +#define CONV3_DS_PY 1 +#define CONV3_OUT_X CONV3_IN_X +#define CONV3_OUT_Y CONV3_IN_Y +#define CONV3_DS_BIAS_LSHIFT 2 +#define CONV3_DS_OUT_RSHIFT 4 +#define CONV3_PW_BIAS_LSHIFT 5 +#define CONV3_PW_OUT_RSHIFT 8 + +#define CONV4_OUT_CH 64 +#define CONV4_IN_X CONV3_OUT_X +#define CONV4_IN_Y CONV3_OUT_Y +#define CONV4_DS_KX 3 +#define CONV4_DS_KY 3 +#define CONV4_DS_SX 1 +#define CONV4_DS_SY 1 +#define CONV4_DS_PX 1 +#define CONV4_DS_PY 1 +#define CONV4_OUT_X CONV4_IN_X +#define CONV4_OUT_Y CONV4_IN_Y +#define CONV4_DS_BIAS_LSHIFT 3 +#define CONV4_DS_OUT_RSHIFT 5 +#define CONV4_PW_BIAS_LSHIFT 5 +#define CONV4_PW_OUT_RSHIFT 7 + +#define CONV5_OUT_CH 64 +#define CONV5_IN_X CONV4_OUT_X +#define CONV5_IN_Y CONV4_OUT_Y +#define CONV5_DS_KX 3 +#define CONV5_DS_KY 3 +#define CONV5_DS_SX 1 +#define CONV5_DS_SY 1 +#define CONV5_DS_PX 1 +#define CONV5_DS_PY 1 +#define CONV5_OUT_X CONV5_IN_X +#define CONV5_OUT_Y CONV5_IN_Y +#define CONV5_DS_BIAS_LSHIFT 3 +#define CONV5_DS_OUT_RSHIFT 5 +#define CONV5_PW_BIAS_LSHIFT 5 +#define CONV5_PW_OUT_RSHIFT 8 + +#define FINAL_FC_BIAS_LSHIFT 2 +#define FINAL_FC_OUT_RSHIFT 7 + +#define SCRATCH_BUFFER_SIZE (2*2*CONV1_OUT_CH*CONV2_DS_KX*CONV2_DS_KY + 2*CONV2_OUT_CH*CONV2_OUT_X*CONV2_OUT_Y) +// max of im2col: (2*2*64*3*3)=2304 + max consecutive layer activations: (64x25x5 + 64x25x5)=16000 + +class DS_CNN : public NN { + + public: + DS_CNN(); + ~DS_CNN(); + void run_nn(q7_t* in_data, q7_t* out_data); + + private: + q7_t* scratch_pad; + q7_t* col_buffer; + q7_t* buffer1; + q7_t* buffer2; + static q7_t const conv1_wt[CONV1_OUT_CH*CONV1_KX*CONV1_KY]; + static q7_t const conv1_bias[CONV1_OUT_CH]; + static q7_t const conv2_ds_wt[CONV1_OUT_CH*CONV2_DS_KX*CONV2_DS_KY]; + static q7_t const conv2_ds_bias[CONV1_OUT_CH]; + static q7_t const conv2_pw_wt[CONV2_OUT_CH*CONV1_OUT_CH]; + static q7_t const conv2_pw_bias[CONV2_OUT_CH]; + static q7_t const conv3_ds_wt[CONV2_OUT_CH*CONV3_DS_KX*CONV3_DS_KY]; + static q7_t const conv3_ds_bias[CONV2_OUT_CH]; + static q7_t const conv3_pw_wt[CONV3_OUT_CH*CONV2_OUT_CH]; + static q7_t const conv3_pw_bias[CONV3_OUT_CH]; + static q7_t const conv4_ds_wt[CONV3_OUT_CH*CONV4_DS_KX*CONV4_DS_KY]; + static q7_t const conv4_ds_bias[CONV3_OUT_CH]; + static q7_t const conv4_pw_wt[CONV4_OUT_CH*CONV3_OUT_CH]; + static q7_t const conv4_pw_bias[CONV4_OUT_CH]; + static q7_t const conv5_ds_wt[CONV4_OUT_CH*CONV5_DS_KX*CONV5_DS_KY]; + static q7_t const conv5_ds_bias[CONV4_OUT_CH]; + static q7_t const conv5_pw_wt[CONV5_OUT_CH*CONV4_OUT_CH]; + static q7_t const conv5_pw_bias[CONV5_OUT_CH]; + static q7_t const final_fc_wt[CONV5_OUT_CH*OUT_DIM]; + static q7_t const final_fc_bias[OUT_DIM]; + +}; + +#endif diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn_weights.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn_weights.h new file mode 100644 index 0000000000000000000000000000000000000000..fbd75ba6e1c0b07c7044f131c162ed36270867d4 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/DS_CNN/ds_cnn_weights.h @@ -0,0 +1,20 @@ +#define CONV1_WT {2,-14,-11,-15,-3,-23,-5,5,-1,-13,0,16,4,5,5,28,5,6,9,17,-1,3,4,4,-8,13,-3,-16,-1,14,0,-22,4,13,-4,-25,6,1,-1,-28,-5,4,7,0,-3,-3,5,6,1,-8,8,9,1,-10,11,4,0,-11,7,9,1,-3,-1,10,1,-5,9,8,2,0,8,6,0,1,11,2,-5,9,13,-3,6,-16,-15,-23,-4,-14,-14,-27,-2,-1,-6,-14,-6,9,5,1,-13,24,7,5,-14,15,8,15,-7,3,14,27,1,0,4,23,1,0,14,20,7,-3,15,6,26,6,25,-8,20,-15,14,-5,-3,-20,13,-2,-15,20,6,-10,-14,23,12,-32,-11,15,-5,-19,-4,10,-20,5,-4,7,-27,19,5,-17,-26,10,8,-17,-24,3,17,20,-6,12,0,19,-14,-8,-23,4,-7,-13,-6,6,0,-6,7,3,6,-5,-4,-20,6,-12,-9,-17,10,-7,-5,-5,12,-10,-10,-2,26,17,0,-5,20,41,7,27,10,6,-12,5,2,-14,-20,-15,3,-9,11,-16,-30,29,38,12,-63,27,30,15,-34,17,28,14,-15,11,16,-5,-3,16,-10,-18,20,7,-22,-20,17,2,1,-6,1,-6,2,-2,-1,7,13,12,16,9,12,30,16,6,-3,19,9,-9,-20,-11,-10,-4,-18,-21,-14,5,-8,-17,-12,6,2,1,-2,-12,1,-5,-2,-16,-3,-11,-19,2,-6,-8,-29,-7,-2,-9,-22,-18,3,-1,12,-18,0,8,32,-6,7,15,33,13,9,15,34,8,10,11,10,-5,-2,1,-5,-5,-13,-2,-10,1,6,-14,-12,1,3,-15,-16,-7,-2,-7,-9,-2,-7,-7,0,10,4,0,-1,1,2,4,-2,-4,5,4,-7,1,10,0,8,6,5,1,3,1,-1,10,2,-9,-10,15,-10,-8,-5,19,-15,-10,-13,8,-9,-22,-10,-1,-2,-20,-5,-9,15,1,4,-12,17,16,9,-19,11,14,4,-19,-8,6,15,-5,0,21,23,17,-1,29,0,-20,-40,40,11,3,-52,0,10,31,-40,-25,0,20,-31,-30,6,-10,-13,-5,-3,-11,4,9,-4,-14,8,6,-3,-9,6,-2,5,-2,1,2,-2,2,-7,9,7,-8,-8,11,13,-2,-21,5,9,4,-24,-7,2,15,-9,-16,-6,19,13,-23,-8,8,33,-21,-3,5,34,-17,-1,2,24,-14,-6,-11,5,1,-1,-14,-1,8,-7,17,16,14,-9,19,15,11,-6,7,11,-7,-10,-9,12,-15,-9,-19,8,-7,-16,-19,7,-6,0,-15,-12,-5,10,-6,-37,8,21,10,-43,-14,18,17,-26,-16,-18,-22,-24,35,-4,-14,-12,32,10,1,-12,11,13,-7,-1,-9,-3,5,10,-5,-10,0,5,5,-20,2,3,5,-10,7,10,3,18,17,13,-32,11,15,4,-42,-6,-2,-14,19,-10,9,-5,15,-3,16,-8,1,-1,18,2,-12,10,8,16,-11,1,2,15,-9,-1,-8,5,-6,-5,-8,1,8,-7,-7,0,6,-8,-9,5,-3,11,-1,-5,7,-9,5,-9,9,-9,11,-8,-8,-16,2,-10,-26,-23,-24,-14,-26,-14,-11,-12,-3,8,4,7,5,17,21,27,-2,23,12,32,-14,18,5,35,-13,32,-12,-16,-10,35,-17,-22,-4,17,-7,-11,7,-5,-6,-4,9,-12,-2,6,21,-10,7,8,18,-3,5,1,20,-15,4,4,13,-38,20,4,8,-28,13,-1,7,-4,-19,-7,-17,-3,-18,-4,-20,3,-4,-2,-16,3,-2,-8,-3,1,-8,-9,3,-1,3,-1,11,7,8,3,11,-2,11,6,3,-3,16,7,10,-3,15,7,6,0,15,3,-3,7,6,11,-2,-4,9,14,-15,-27,14,28,-42,-13,9,32,-22,-7,-6,5,11,5,-16,0,41,9,-6,-12,55,22,-13,-28,12,9,-9,-32,-16,-12,-16,8,7,6,-14,18,6,14,-15,12,17,-10,10,-5,7,-10,-2,11,-4,2,7,10,-1,5,7,-1,15,-7,4,-1,17,-7,8,-6,3,15,25,-7,22,16,5,-10,-14,8,-9,-19,-33,4,-11,-39,-27,-10,1,-12,7,-2,12,26,35,-8,24,45,28,2,19,12,9,2,-3,-15,-20,1,-14,-20,-12,-4,-8,-4,-4,-11,-13,22,-10,5,1,7,-23,14,-14,2,-24,8,-17,-2,-9,1,-3,0,6,-1,3,-1,1,-4,-1,5,3,2,15,-7,-8,3,8,-3,1,14,-2,0,3,-19,4,25,-1,-9,2,9,1,-9,-22,7,-3,11,-6,-3,-2,-1,13,-13,1,0,4,-11,17,-1,-6,-5,11,4,-16,-6,14,10,-11,-10,1,9,10,-12,-3,-10,-15,8,-1,-8,-10,21,17,-10,-8,23,29,8,-2,-2,31,1,3,-29,18,-2,23,-27,-10,-2,14,-9,-1,-8,7,8,12,8,-2,3,10,23,5,-18,0,16,6,9,3,15,3,19,-10,4,12,14,-22,14,17,8,-22,10,12,-8,-7,-5,7,-15,2,-11,-13,-8,0,-5,-10,-11,-5,-8,-7,0,-8,-12,-16,9,-7,-6,-7,5,20,-3,-9,9,24,-9,-12,12,13,0,-8,0,-14,5,1,-16,-40,15,5,-27,-54,8,15,-17,-29,6,14,1,6,4,13,10,8,13,4,3,-2,15,16,-13,20,18,6,-9,10,-9,21,1,18,-3,12,20,9,-7,-5,30,-3,-8,-15,17,-16,5,-4,-1,-10,2,-8,-3,3,-14,-15,-4,9,-9,-7,-17,-7,21,-7,-6,-10,0,-11,-8,-27,-1,-4,-30,-22,21,12,-6,-30,13,6,16,-43,-37,15,11,-28,-55,2,1,10,-29,-21,-2,26,-15,-22,-15,37,-3,6,-14,16,-9,17,9,7,1,13,5,19,-2,8,6,20,-9,5,5,27,3,10,-8,21,-6,-5,-1,13,-8,-6,-2,0,8,-12,-7,14,-1,-4,-5,14,-1,-20,-1,13,-9,8,15,-4,-9,8,10,-16,-18,18,-5,-15,-15,13,-14,-19,2,8,-10,-7,9,-6,-8,6,7,-13,-3,11,-1,-9,5,-2,4,-5,7,-5,19,-11,4,1,27,-6,-15,-10,33,-10,-2,-11,27,-6,-2,-11,21,-7,-3,-21,15,-11,-9,17,-7,3,3,41,-13,18,20,46,-20,7,3,39,-49,12,7,21,-41,13,14,3,-21,11,-4,-12,-1,-5,13,3,8,-16,23,15,8,-15,-1,22,8,-17,-30,23,1,-6,-31,15,2,14,-17,6,4,21,-1,-4,3,18,11,-21,-3,1,12,-17,4,-1,-2,2,-6,-2,3,4,-10,-4,8,7,1,-15,8,-2,3,-2,17,-1,1,6,21,9,3,19,5,1,4,7,-5,-7,-2,11,-7,-19,-10,5,-7,-22,-19,5,9,-40,-7,16,-7,-62,8,7,-14,-45,1,-3,2,-26,-5,-2,12,4,-5,1,14,29,-6,12,-1,40,3,4,-2,24,14,-2,2,28,14,-11,3,20,3,-8,-4,20,-3,-8,-1,18,-11,-5,12,-2,-12,1,22,-8,-6,12,16,-1,-1,11,1,3,-5,10,-5,7,3,5,-6,-11,17,4,2,-26,13,1,6,-26,-3,24,2,-11,0,5,8,-12,-10,11,9,-10,-6,5,20,-10,4,1,13,-22,5,3,7,-11,-2,-10,10,6,-10,-5,8,14,-3,-15,3,27,-2,-6,-14,23,-1,-6,3,-8,4,-2,-6,-7,11,-2,-5,4,3,-1,0,5,-8,0,5,-7,-5,-12,1,-14,-6,-5,-10,-17,-7,12,3,-23,20,32,22,-17,16,7,27,-1,-15,-8,7,6,-3,-5,-4,-3,-4,-8,-4,-2,0,1,-15,-3,4,7,-7,-4,7,-8,-2,-3,1,7,10,-1,1,10,17,-6,7,18,19,-3,17,9,4,-9,8,-2,-3,-14,11,-1,0,-1,-2,-5,15,4,-8,-12,20,11,-19,-16,22,11,-14,-6,3,20,-26,-3,7,12,-13,13,12,10,-6,12,5,16,8,2,9,4,-9,-23,-2,17,-21,-16,14,-20,-38,-3,18,-23,-52,8,9,24,-31,10,-2,51,-6,11,-3,40,26,17,-11,-5,41,5,-11,-46,42,2,-17,-44,22,-4,-6,-10,9,0,-4,0,7,7,-10,-2,6,20,-14,-6,5,19,-20,-16,-2,10,-18,-3,-12,-9,4,3,-22,-16,9,3,-7,-18,8,-8,10,-6,1,-11,11,-1,9,3,-1,-3,-4,10,-2,-8,-8,2,-1,-12,3,11,-2,-5,1,14,-1,7,8,12,-1,13,23,12,6,14,19,-6,0,7,9,-12,7,5,6,-2,9,3,5,5,21,-8,22,3,17,-13,10,9,20,-15,7,22,9,-4,-14,24,-6,4,-20,0,-25,15,8,-3,-22,13,9,-35,0,3,-18,-41,5,7,-7,-33,-3,12,6,-3,16,4,-54,46,9,5,-73,56,-11,0,-55,51,-13,-3,-22,39,-15,-20,4,27,-2,-6,10,-4,6,-10,4,-4,20,0,6,-5,18,17,16,-7,23,10,19,6,0,3,2,3,5,-9,4,13,-6,-12,5,7,-13,-8,-6,-20,-9,21,0,-38,-3,28,2,-14,9,10,13,5,-2,-5,2,22,1,-6,-7,12,-8,-3,1,11,-7,-16,2,4,-11,-17,-7,11,-2,-12,-6,9,4,-9,3,0,-3,3,-1,-2,1,8,-4,1,7,13,-1,0,8,7,-5,7,9,11,5,5,-4,10,7,6,2,16,-6,-22,16,13,19,-3,9,-1,18,11,-3,-26,-15,2,-9,-6,-21,-24,6,6,21,-2,10,25,14,-14,-5,2,7,-16,-8,-2,1,-4,-8,-3,13,-24,-10,15,-31,-10,10,3,-35,6,9,-1,-21,12,-8,-8,-18,5,-3,-19,-3,4,1,-21,3,11,2,-10,4,9,12,5,11,18,0,19,13,11,-2,8,6,-1,-2,-2,-20,46,9,14,-18,35,5,12,-9,19,-10,11,-2,2,-25,2,2,-12,-27,-1,11,-17,-24,-23,-5,-42,-6,-8,-21,-45,2,-9,-21,-35,-1,-12,-10,-12,-8,3,15,-1,2,6,8,-4,9,10,-3,-5,7,1,0,-3,-2,3,7,-4,-6,1,9,3,-8,2,11,-1,-4,-2,6,-2,-4,0,6,-12,-2,7,8,-10,-18,5,12,-1,-3,-23,29,-2,-5,-21,-7,-23,17,5,-34,-7,23,14,20,43,-7,11,32,24,-10,14,0,-21,7,6,-7,-32,3,2,1,-19,6,6,-3,0,-15,19,0,2,-8,13,2,-5,6,12,6,-10,11,1,11,-11,7,3,4,-16,3,0,2,-12,6,-14,0,-5,9,-9,-5,10,4,-2,2,26,-14,-4,16,28,-10,11,-13,-15,-10,10,-1,-15,-3,-14,-2,-1,5,-15,-5,-11,-8,-13,-4,-1,-6,-12,-3,-2,-6,-9,-1,1,-3,7,7,-6,4,6,17,-6,-10,13,18,-3,-5,1,-11,-1,-6,-4,-15,-2,-12,-2,-3,0,-8,-9,-14,6,-3,-13,-1,-4,-8,-11,9,11,0,-14,0,4,-4,2,-15,6,-5,20,0,4,-11,11,21,2,-4,-6,4,-2,3,-2,8,-9,4,16,8,-1,8,20,-1,5,3,19,-20,-4,3,4,-33,0,4,-11,-23,10,2,-21,6,-3,-9,-11,12,-11,-10,0,7,-9,0,24,7,-20,4,11,-4,5,-2,-14,1,11,-7,-10,1,16,2,4,9,19,2,4,19,12,-11,8,14,4,-4,-15,-1,10,0,-22,-3,-10,-4,-7,-13,3,25,-19,-1,-34,26,-23,-8,-40,21,4,0,-16,11,6,1,-8,3,24,-1,-3,-6,29,8,4,-20,-2,7,21,-27,-19,6,13,-25,-7,-1,27,-6,4,-12,18,10,-3,8,29,-7,-7,10,12,-11,-14,3,11,-1,-8,-4,-3,6,-2,14,0,12,-7,1,2,10,-13,-12,-7,17,-2,-7,3,11,21,-6,14,-2,23,3,-3,-2,13,33,-26,10,15,33,-18,9,-2,33,1,-9,-19,17,18,-8,-26,4,21,-2,-17,-8,16,2,6,-23,5,-6,12,-22,2,-1,6,-50,2,-6,9,-52,-10,-5,3,-16,5,-3,-2,-12,4,-4,-9,-4,-1,-9,-3,0,-8,1,0,7,-6,3,9,9,-2,-4,12,9,-1,-1,9,8,-6,0,8,18,-9,8,1,17,0,8,-18,-24,4,8,-11,-26,-6,8,-9,-22,-39,1,11,-15,-58,-4,3,7,-49,-5,-2,26,-24,-11,-13,35,2,-5,-1,4,7,-3,7,1,11,2,6,16,17,1,-3,16,-25,-5,3,-2,-10,11,2,-27,5,16,-14,-23,40,23,-15,8,11,-9,16,16,-31,-17,22,6,-28,-20,-1,5,0,-29,4,7,13,-15,10,13,-6,11,1,-15,-10,8,0,-12,-16,-4,5,5,-13,-12,14,1,-1,0,-1,-6,1,7,-15,-9,18,8,-14,-7,15,6,-6,2,3,-18,-1,14,3,-18,-8,23,8,-12,4,-9,2,-6,-11,-7,-15,-3,-16,0,3,5,-19,-11,26,2,-2,-7,1,2,31,-1,-42,4,26,9,-9,2,3,11,14,22,-7,7,11,21,-4,6,5} +#define CONV1_BIAS {50, -25, 50, 19, 16, 35, 42, 52, -41, 5, 3, 100, 13, 0, 26, 63, 9, 60, 78, 29, 111, -20, -26, 68, 49, 52, -4, -19, -5, 70, 19, 30, 62, 27, 53, 61, 47, 84, -4, 92, 51, 113, 18, -13, 91, 26, 71, 28, -7, 41, 26, 32, 12, -15, 86, -17, 24, 4, 31, 39, -7, 35, -25, 71} +#define CONV2_DS_WT {7,3,21,2,-14,22,44,-44,-18,-25,5,19,-31,-19,30,-40,-52,-23,-1,-30,6,-14,33,-31,-29,17,-20,-36,-34,9,34,29,21,44,42,-13,34,-36,-13,-7,-27,66,-46,-1,-58,5,11,-8,9,44,0,75,4,-32,6,18,-16,17,-5,56,-26,-3,-21,22,4,-13,29,21,-41,-14,-13,-7,5,-4,13,6,-13,11,51,-15,-2,6,-23,25,-50,-31,35,-53,-30,-41,36,-1,-10,34,-23,-10,-1,-20,-15,26,33,-42,-13,12,42,-7,42,-34,22,-21,24,14,33,-54,-15,0,2,-17,35,21,3,13,-19,22,20,-25,36,-11,-4,17,-20,-12,23,-22,-7,30,-17,-7,-66,-51,3,12,7,54,-17,13,27,-2,66,-38,44,-14,24,-33,55,-4,9,-40,2,12,-41,-54,125,-19,28,-30,21,-7,40,-50,39,-22,52,9,-13,16,4,62,-8,-50,8,-10,-70,-5,45,-18,6,72,-3,-23,-43,-6,29,4,8,-17,-20,23,-5,-9,-10,-20,-16,24,8,-18,39,-2,2,-8,-24,26,-41,11,-12,-9,-34,15,18,6,-20,-14,8,-9,-37,-30,15,-6,-17,-42,7,32,-4,5,41,-4,8,-8,-54,-19,-23,-37,-51,-10,7,33,-37,31,-29,-31,-2,-6,6,52,32,-15,16,-21,6,21,11,-3,-27,-13,-13,-5,32,-37,-8,23,19,-16,-21,6,13,18,53,6,-21,46,-4,28,-24,32,-22,26,-6,-22,-12,13,-22,18,-12,-17,-8,-14,3,18,3,14,-64,4,-26,-21,-9,73,40,-11,20,11,-16,-4,17,-19,-17,-70,-23,-13,13,38,-33,42,-4,5,1,-14,-3,36,-6,-13,-3,-26,7,27,65,25,16,14,15,-9,-27,6,14,30,17,-29,-1,-3,-19,11,18,61,-47,-57,27,21,16,38,5,-18,-12,4,20,7,-1,-1,21,18,-28,-31,-7,1,-11,-21,38,-51,1,-4,-3,16,-18,-40,34,-14,17,-23,18,-46,-1,-43,-41,47,-10,4,-12,4,10,-1,-28,44,11,-21,-10,-21,37,14,-24,6,6,4,29,7,-7,-36,9,-18,-34,-15,-49,-29,-46,35,16,16,11,-31,-10,-22,59,-36,44,11,-18,-116,56,-34,3,17,2,-32,-27,0,-26,-54,14,-46,-26,22,-15,3,-58,-52,-1,18,26,-30,15,-11,-41,-18,-6,4,21,-11,-4,6,27,13,7,36,-21,19,8,27,-7,-12,-1,-29,-23,-1,44,54,22,-3,-37,59,-16,-15,-39,-20,-34,27,33,-14,10,-17,-19,-11,-9,-17,14,7,-17,-4,15,40,11,5,-20,21,-43,-29,4,30,-82,-28,-40,-6,14,5,2,-7,40,29,69,29,-7,-27,39,38,-21,-31,-36,-2,38,-10,-4,27,-37,9,-13,13,-18,10,31,-30,-33,-2,-35,-25,-45,0,-17,-5,-12,25,-3,2,-29,19,5,-42,-36,13,-5,11,90,-39,3,7,10,86,-28,14,53,14} +#define CONV2_DS_BIAS {-24, 22, 73, 72, 69, 35, 18, 7, 21, 68, 19, 86, 21, -9, -109, 17, 44, -1, 28, -3, -23, -30, -16, 4, 71, -22, -21, -8, 61, 18, 1, -6, 53, 44, -81, 9, 22, 61, 43, 8, 40, 17, -3, 17, -62, 102, 24, 20, 23, 69, 1, 22, -37, -8, -44, -5, 5, -5, 77, -58, 48, 33, -2, -14} +#define CONV2_PW_WT {10,-10,-6,25,5,31,-54,-31,23,-13,-14,-7,-24,-7,-37,-18,-18,-30,-46,26,-4,-13,-37,15,10,-2,4,-1,-19,37,-19,-5,18,23,-18,32,-47,10,-13,7,50,25,-28,23,5,-7,28,-27,-14,-20,-22,54,13,-35,-12,-7,2,-27,8,18,-4,2,0,-59,23,23,-17,20,29,-38,-13,-43,-2,1,1,5,2,-11,-2,8,-13,6,-56,17,22,-30,-23,-32,-19,-20,25,-4,-17,-23,11,-40,-26,20,62,5,40,-52,14,19,10,-18,-60,45,-4,15,13,-5,-7,17,-51,-18,19,-27,-42,-17,11,20,-13,-9,25,3,-2,11,14,-4,-13,-20,33,-22,-32,39,-25,22,-12,13,-5,35,-37,-29,-22,-8,14,-16,-17,-42,-9,26,-31,29,-53,20,-4,-18,-24,11,36,3,29,-38,18,-4,36,9,26,2,-5,-9,54,-26,-44,-3,26,47,-20,39,-45,-5,11,-20,18,3,-23,-30,2,-36,27,28,3,-25,-20,28,8,42,-73,25,16,33,-5,-5,0,-2,-64,-39,-8,-11,21,25,26,0,30,-33,17,-22,7,13,-12,-38,10,55,34,0,21,-34,-8,55,-38,-1,18,9,-40,20,-33,51,-9,48,52,47,-20,4,-4,-12,17,-12,-44,14,2,13,-21,10,10,-8,35,-18,-46,-46,54,-25,-14,-28,-9,-20,-47,15,-33,-43,19,58,24,17,-30,12,20,16,-17,12,15,-13,-22,28,-6,18,15,14,44,3,1,-53,40,29,-48,0,28,47,17,25,20,20,28,48,-3,10,-32,-60,-50,6,-56,-4,38,-18,43,24,-6,24,-23,-30,18,-30,8,8,-39,-49,20,-31,-29,-4,-32,-28,-19,14,19,-29,-11,-15,11,-20,44,2,-9,0,13,-1,-44,13,-9,-5,19,-1,-18,-3,3,-35,-49,11,-4,6,-3,-35,4,-36,0,-13,1,10,14,12,37,-15,-8,-31,44,-47,-3,33,-7,-42,11,-25,27,7,26,0,43,-25,14,57,-28,-32,-12,31,21,1,7,-28,-20,14,-11,-66,6,-20,20,-43,-24,16,-41,2,-62,32,-17,20,-25,-12,54,0,-17,-28,20,-3,18,-12,0,-38,13,21,34,39,18,28,-27,8,49,44,-10,35,-40,-51,36,25,-42,-55,-25,-44,-7,22,49,4,21,-34,6,-40,14,18,-28,-46,-25,-14,31,-43,4,17,-18,-29,58,10,11,-35,19,-34,22,-28,-1,-58,-65,10,10,-14,15,-46,5,-36,29,-46,22,6,57,3,-11,28,-26,-23,28,-30,-27,1,16,-29,-27,34,3,12,11,59,23,-16,-9,-36,7,25,14,-19,-18,37,-27,22,-28,6,-2,-8,-34,-34,-35,2,17,30,-23,17,5,15,21,-37,6,6,5,18,-6,34,-4,49,-39,3,1,-14,18,21,-31,5,-32,19,23,-49,-21,44,2,-16,20,-6,34,-9,-27,33,-53,9,37,-49,59,-46,-2,1,-23,7,-30,12,-14,8,15,-1,7,2,14,22,-6,-1,-11,-44,16,-23,-15,-15,8,-14,-8,-60,-4,-19,-8,1,-29,43,-17,1,-50,32,26,3,-15,-19,-29,-13,15,-23,-48,-26,50,30,1,11,47,28,-28,-3,17,-21,34,28,9,-6,28,20,-19,-1,10,-21,42,14,-36,-41,-29,54,-1,2,9,-13,20,-32,-67,42,59,-26,52,34,-1,36,-33,22,-24,6,-4,18,-24,29,15,19,-9,-8,30,-23,-50,48,28,25,26,-54,10,-21,-19,48,12,-4,27,-1,30,47,20,45,-11,13,19,-36,-48,2,15,46,-46,-7,18,-7,-57,-15,-46,19,7,-12,-33,-37,16,-3,86,-23,12,2,22,19,-32,3,-22,3,-77,42,-15,18,-8,3,-50,-21,-1,-29,5,23,32,17,-17,16,26,29,-38,-24,-66,-29,41,18,12,42,-9,28,4,28,12,-12,-7,-21,50,7,11,-14,4,-48,-72,-49,6,11,-67,37,-33,15,16,3,18,25,19,5,-38,23,-29,-7,-9,-40,-50,-8,20,-42,26,36,-35,-70,8,-40,21,2,31,38,31,-46,-26,52,8,7,-24,5,-62,3,4,-11,-35,-19,-3,-14,5,-17,38,8,14,28,40,14,-22,5,12,-37,41,3,12,2,-15,14,-37,6,-14,19,-30,4,-39,-21,12,-38,10,-28,2,24,18,-35,4,-7,-29,3,-32,29,32,26,-36,-39,10,34,2,32,25,-7,-17,18,20,13,-22,37,-13,-47,-9,39,-10,-34,-15,-48,24,4,23,-29,2,-22,-36,4,15,1,-6,25,-12,-7,32,-24,37,-27,-7,-4,-33,-21,0,30,1,-18,-30,29,-53,-19,10,-30,-5,-22,3,20,-15,-24,14,9,33,20,19,-15,-21,24,-13,-28,1,11,-16,14,11,18,-51,3,17,-14,-18,2,-3,-81,10,-37,31,-36,-7,10,-29,20,11,-10,-33,20,31,33,-30,-33,-27,3,37,-36,-28,-23,-25,-16,-9,7,4,6,16,-8,19,19,25,12,-4,-9,4,3,-19,17,14,-20,-26,-26,-10,-23,-2,3,6,2,-13,-26,19,-15,-13,-28,-1,7,27,-36,5,18,6,10,-15,-9,-16,-11,12,20,0,-13,-27,-15,-8,20,-22,14,-1,-7,-2,-21,9,6,-34,-2,12,-20,11,-46,-24,-15,-31,-22,-32,2,-4,47,8,9,3,-11,7,-9,-36,-8,9,-25,6,8,-16,-22,4,-20,3,-15,11,-21,2,-41,19,-18,18,-22,5,-4,-10,20,19,28,-47,42,18,-26,-28,-4,-23,25,-31,-28,-22,-26,18,-9,2,2,24,0,8,8,36,-19,-28,1,-14,-40,21,-37,-11,-8,6,33,-8,-8,-4,1,-32,11,-29,4,20,28,-12,7,-9,-23,-10,28,-34,-20,18,-32,-19,18,25,7,18,-34,6,5,-32,-2,0,0,-32,-10,5,-37,-20,29,-11,-13,-5,-8,-15,4,20,-20,0,21,-19,2,13,-13,13,-5,-76,-14,38,-12,9,31,-46,-2,-48,-50,10,33,26,28,35,1,-43,62,-41,-2,3,-17,-19,4,-20,7,9,-10,-65,42,30,-30,-14,-17,14,22,36,-34,-1,-20,-43,2,31,8,4,34,-23,-36,-62,41,35,0,12,37,41,-37,-11,-55,-9,19,20,-23,-7,4,29,-3,-1,16,14,-5,-1,-20,12,-5,-44,-53,16,6,-15,-40,0,3,-31,-1,-28,-25,-2,4,-4,22,21,22,-6,-14,48,2,17,21,-22,-13,-12,2,-26,-16,11,-10,13,-14,56,-40,-17,22,-47,-10,-19,15,-10,-27,-2,-18,-3,1,-33,3,-17,30,-10,-35,-9,-3,3,-31,-20,-18,24,-6,16,-2,22,-4,42,24,-30,12,-24,15,37,13,-4,-35,-40,26,74,5,-45,-14,23,22,-1,-26,-18,-16,15,-27,-18,40,-20,-12,-5,13,-7,34,20,-17,4,-46,-40,-20,17,-30,31,1,63,-9,-28,21,35,-46,20,-25,-13,-10,-47,-15,-8,18,-12,29,-5,7,27,-17,-9,-29,3,-38,49,1,-31,2,-38,4,46,14,20,-17,15,24,2,7,-18,-6,-28,-2,4,-21,-18,-29,-1,10,-2,-24,40,35,-8,30,14,44,-1,-67,-11,-1,-60,-14,29,18,24,-46,-22,-11,41,-39,0,4,-20,-3,25,-26,-30,37,-17,5,-16,-17,-6,5,40,-61,13,3,16,-39,17,-14,17,10,-22,29,-1,-10,-29,-6,2,22,-3,2,12,-1,10,25,20,41,10,13,9,-1,-15,-10,0,4,-15,28,-24,10,18,-13,35,-40,30,-1,14,15,-6,3,-16,-12,19,16,-3,1,9,-1,7,1,39,26,-51,23,-75,9,-12,67,21,0,-52,8,-30,12,-7,-13,25,3,-1,-4,-8,45,14,-3,36,-8,41,32,0,28,11,0,5,-33,12,-22,0,-27,-10,-16,23,31,1,10,-12,-27,10,-22,-23,7,-3,34,-17,-31,17,-17,5,-5,-7,-11,7,-7,-7,-15,-28,12,-5,-18,-16,-13,2,44,26,28,26,-11,-20,11,41,2,6,-22,48,-3,13,-26,16,-6,-21,27,-17,33,-7,2,-31,43,23,20,-28,3,15,15,23,-13,21,39,-17,37,-18,-10,-14,-11,-9,-6,0,-2,42,-5,25,16,-46,-34,-16,10,7,-32,-35,5,43,4,-5,31,9,-12,27,-2,-1,22,-42,-4,-10,61,-19,11,-21,-38,-7,44,9,-59,-15,25,16,13,25,-37,22,29,-4,-19,38,-25,-37,-24,-29,-21,3,10,0,-25,-29,55,49,22,-1,26,-11,16,46,-40,39,-22,20,-20,-23,-8,9,3,-36,20,-10,-5,-9,-45,-18,-42,55,28,11,16,34,21,16,18,-24,25,-22,31,0,21,-2,-45,-30,5,-36,49,-18,21,-3,28,0,18,11,-4,-12,21,3,5,27,-31,1,3,-19,81,-2,22,-28,53,-9,0,-36,-14,-17,-27,19,-4,-40,12,9,-14,-2,-38,-71,76,3,49,51,-30,-11,13,22,43,31,-23,-6,21,-12,18,-3,1,13,6,1,51,-14,25,-28,31,-12,-18,-49,-20,-44,45,-11,15,-5,-14,-52,-23,-44,-10,6,34,3,-29,-31,32,36,22,8,38,25,-57,-26,0,42,0,5,-29,-14,30,14,-2,46,53,-24,-22,-15,3,-32,49,-49,-30,-18,11,-46,11,-4,-15,-6,-13,30,-3,8,31,12,-42,-8,-7,-42,6,-18,21,3,15,28,-33,-16,8,-1,53,34,2,38,-33,-27,-62,11,-36,19,2,-19,22,1,3,21,-26,-7,1,-5,-25,-3,3,14,36,0,37,-3,-40,38,49,-27,-17,-27,3,-18,77,-28,40,24,17,43,-67,44,-5,3,-18,51,17,-46,-44,-29,12,-41,15,-18,-46,-13,-25,-15,3,5,-10,-27,34,-26,17,27,9,62,34,5,16,48,0,7,25,-5,-8,1,36,-32,-57,-2,13,18,47,-16,-51,58,26,-25,27,1,-39,-3,20,-15,-23,32,-9,3,-19,-22,18,-10,-45,-21,17,-5,-7,-5,-5,37,-18,8,15,-3,25,6,-12,-30,-50,-11,10,8,-26,-6,14,-25,-12,9,31,8,-2,0,12,-21,31,-18,28,-35,-15,-18,16,-34,-14,-14,24,-5,-23,-43,3,12,10,-13,0,28,5,-36,-11,-36,-26,11,-31,23,-45,2,20,4,39,23,4,-29,63,-2,-12,-1,-10,13,-41,-29,-12,28,-12,19,-6,22,1,17,-1,-8,-37,-5,-20,2,-22,-33,4,-35,-24,3,18,44,11,-39,-7,20,20,-1,-47,0,-29,7,-11,-34,7,1,9,-45,-39,5,17,-18,-23,-8,25,67,2,-17,30,-10,-15,-30,36,-12,-43,-9,-14,15,-10,46,13,20,4,27,-20,-17,0,26,22,3,-10,-2,-29,25,-20,-43,-1,14,-7,-17,-55,21,-33,-8,11,36,11,8,0,47,39,2,4,30,-4,-36,0,22,-10,4,2,0,-3,-20,-5,6,-31,26,-36,-45,-27,-38,45,-3,-33,64,-48,-46,-26,41,47,-10,17,0,7,33,-6,-89,-9,-41,-17,47,-49,26,23,-47,38,-13,-18,9,-41,48,14,1,-21,25,2,-9,50,-17,-7,21,9,54,-10,-25,35,19,43,2,-4,44,-2,-33,3,40,30,-22,-6,24,56,32,19,22,-33,-34,-5,16,13,-3,5,-14,10,-23,15,-10,-14,-5,2,-7,39,-54,32,-13,29,31,32,-11,-39,-17,33,-12,-23,-28,31,2,-59,-19,-5,-13,-17,35,-3,24,4,-14,31,-25,46,-21,-8,16,32,4,34,-53,-52,23,50,-37,-11,-38,-9,43,19,9,-19,-21,-19,-29,17,-1,-6,23,19,19,-18,9,-1,33,-2,18,-45,2,-18,-3,24,-29,23,16,-43,-32,15,19,2,23,-21,-14,5,-28,15,-10,4,9,-1,-5,9,3,26,11,17,-8,7,0,-10,27,-45,7,0,28,-34,-3,-20,2,26,-4,7,-61,1,-36,-21,-23,-56,31,38,32,-6,-18,7,3,-2,6,-13,55,26,19,32,-3,6,29,-15,14,-15,-11,-23,22,52,-57,16,-62,43,-6,-42,9,-32,23,52,13,-65,-2,65,-25,-5,-17,33,-36,-16,9,8,-66,26,50,11,20,6,15,37,25,33,-19,-25,-13,19,32,21,-43,-31,-26,-13,-11,-12,-6,-6,-15,27,-58,23,5,21,-19,-35,42,-15,-17,5,-4,-29,-10,18,12,9,-14,-1,-33,-34,-35,25,6,-42,-34,33,-9,-7,-20,17,4,-23,-19,-31,10,3,-19,18,-7,-38,12,34,-9,10,-34,-25,-8,6,8,-17,-25,-10,16,0,18,8,-14,-23,-23,19,4,23,-1,-17,11,-2,7,21,13,-25,-23,-17,10,3,-33,4,13,-23,8,2,-14,25,38,14,-17,-5,3,28,-13,20,-6,-11,-2,-2,-17,14,-25,-4,8,9,-23,-15,9,-36,-7,-29,-9,5,-21,20,13,0,-4,40,-13,13,30,8,-45,19,-11,11,-15,27,21,9,-35,-24,-11,-13,27,5,7,-5,-15,-49,32,39,-36,26,10,6,-21,29,-12,-10,-6,12,-24,-7,19,19,0,14,-1,8,21,-47,0,-6,20,-19,12,-25,-12,-18,14,-31,0,-33,18,-15,-22,28,-22,-16,4,-10,-35,-13,2,0,41,15,-4,-27,-2,-10,-50,3,-42,7,6,22,20,-29,0,-16,-36,8,-33,4,-6,37,36,-20,-24,-26,11,-12,-10,-39,39,13,-21,26,36,20,-12,34,25,32,-28,14,7,-19,8,66,32,34,0,-31,30,25,-33,25,-45,-13,22,27,-34,24,23,23,23,-16,-13,9,12,-10,4,-2,-3,30,17,-9,9,28,10,-23,26,-24,-8,6,-6,39,-23,-5,-1,-29,-31,-8,16,-8,9,7,18,32,8,5,29,-25,-45,5,-8,13,6,22,-6,0,-41,-16,-1,-55,-2,-20,7,28,-7,-9,4,17,-33,-15,25,40,42,35,-1,27,-58,37,46,-24,26,-27,24,11,-20,-37,-5,22,-6,-36,-23,25,-4,-62,20,8,-47,9,-28,-17,-9,8,30,13,9,-40,-30,-11,22,-14,40,-43,-14,9,38,-21,-10,-50,6,11,27,2,-7,-32,60,-17,-17,25,-22,21,-11,21,-6,11,-12,36,-6,-26,-34,14,5,-18,-49,-43,-5,-12,-73,-32,39,-15,-31,9,18,6,5,13,-10,-65,19,-23,-2,-18,32,1,5,-28,-2,-10,15,1,33,-3,-50,6,13,13,-53,-12,54,21,78,-19,-22,7,75,-30,27,40,57,12,23,-35,-13,14,-8,20,26,19,0,-61,0,35,17,-28,33,5,-3,-21,-3,-52,33,-50,41,5,10,47,21,-34,-9,13,11,-28,32,-31,-42,16,7,-8,-4,-18,-10,21,-3,7,-15,-6,-16,25,-1,-9,-43,-42,8,-50,-53,-38,9,-4,-30,-15,3,-32,-31,-11,48,25,47,11,-47,0,29,46,16,-19,-21,-10,-16,-39,-18,-6,-11,22,0,-12,13,7,-14,-18,23,27,-13,16,-40,-2,-19,46,-13,-26,6,8,10,-34,3,-7,15,-38,2,19,-4,-13,-28,-14,33,-40,-32,-45,-2,15,-32,-12,7,18,24,20,12,-39,33,-40,19,19,0,11,-6,20,13,-11,-18,-5,18,-30,-57,-18,-1,41,30,-63,-25,32,17,-17,-10,-45,27,24,14,20,23,-1,-51,5,-4,-19,-19,15,-10,-32,-37,-17,-27,8,47,14,9,-5,36,-32,5,-28,-40,-24,20,34,-30,9,-51,5,19,12,35,26,17,27,31,-4,36,50,9,5,-39,-24,38,1,20,-65,-44,-14,16,-55,20,0,21,19,9,23,-32,9,-12,4,-28,-7,31,0,22,-20,-14,13,21,-25,-45,-28,2,5,31,0,5,18,18,-10,12,30,36,18,-40,31,-13,38,28,44,-54,-7,21,-15,-35,26,-8,-6,-26,-11,-11,-2,21,-12,-1,28,-26,41,-20,-5,13,10,50,6,-2,-11,1,-2,10,-34,18,20,21,38,-16,17,-12,-5,-12,2,-9,-23,-33,-11,14,-28,6,-1,-28,-19,-13,-54,23,14,-30,34,-52,10,-13,-16,27,66,3,-6,-18,36,-4,5,-9,-39,-3,31,35,-30,16,-21,15,-17,27,36,17,24,8,-20,11,-25,-16,13,-23,41,18,10,6,-7,-7,3,6,-10,-34,-23,-1,18,-19,-11,21,-7,-25,15,8,28,-7,-47,-9,-9,27,23,-32,-53,12,10,-20,17,-29,20,29,-30,-33,-27,-31,0,-33,-40,16,-14,28,10,-17,-30,36,-1,-12,38,-3,-32,42,-9,16,-35,-1,16,13,-37,24,40,-2,13,-32,-10,-20,-30,-60,-15,12,4,-17,-5,-44,30,45,-73,4,12,18,5,19,3,11,-11,-11,15,27,0,-57,15,-14,52,2,7,22,-68,-33,-32,25,31,-22,23,-32,23,-14,-6,-15,-16,-2,26,-7,8,-4,-21,-22,2,2,12,-2,-26,27,25,13,12,48,20,21,57,-5,-11,-11,61,22,23,-3,-23,-3,14,-2,-4,-16,-24,-22,-8,-17,-12,23,14,-4,-3,-25,12,21,-20,1,11,24,11,6,-48,-46,-42,9,-11,-40,-4,27,39,-17,-3,4,-4,17,22,23,5,4,-64,-45,9,-5,9,13,-18,4,-16,7,9,-19,-16,23,-6,15,-19,22,-14,15,-3,5,-31,-16,-24,12,-14,1,-12,-28,-20,-36,0,11,-10,16,16,-23,34,-8,-2,16,-17,13,12,-12,34,16,15,10,5,-6,-13,-24,-9,3,-10,-31,24,44,-8,9,-6,-4,-9,18,-45,-3,-7,28,26,-4,6,66,49,-21,-7,-40,-25,-27,5,-25,-14,-44,43,4,20,-39,45,20,25,30,40,-23,-31,26,9,2,-14,-7,-3,15,-1,-45,-12,8,26,-26,-16,54,38,-5,-28,-24,12,-11,-8,-2,29,7,10,-8,43,-16,13,-17,16,-22,19,-24,18,38,33,-27,-38,-20,3,-23,5,12,-69,-26,-39,-18,-52,66,8,-23,-17,21,-18,-3,-30,-54,11,-3,18,-31,-15,22,34,1,53,22,-9,10,-7,-28,-3,-50,18,-43,25,32,1,52,5,18,-42,-2,-39,41,-9,-26,-28,-9,-4,53,-27,13,47,42,24,23,16,-4,-14,18,-18,12,-15,19,4,6,-2,7,-14,4,16,-18,-25,41,-22,22,-26,4,25,16,8,-16,2,17,-36,0,36,-32,8,3,14,-21,-13,-34,21,35,7,11,-9,-5,-18,-3,-25,-20,13,13,14,-4,-36,-9,-29,-15,25,21,2,-8,-8,-45,-28,-33,-1,8,-10,-25,8,-35,-2,-2,35,0,17,-30,16,-11,-26,35,-7,-6,-17,2,-1,-39,12,-9,-31,-16,20,-11,29,17,30,-21,-30,7,22,26,-1,-14,-19,4,-10,31,-38,-31,52,-1,-6,-6,5,-17,-20,-4,1,3,-22,-9,-24,21,9,-13,11,-8,-3,20,-5,13,-29,4,2,-24,-17,-37,-2,24,-55,-7,2,-8,-13,3,17,-44,-8,18,24,-15,-34,-9,-16,5,-22,-5,59,-31,7,27,-11,3,40,19,2,-12,-18,50,-11,14,-16,24,-5,-3,-25,-40,10,32,32,-42,1,45,23,5,-11,25,7,21,-13,-6,-61,2,-8,-3,-7,-18,-1,-56,14,-26,20,1,17,21,34,-10,-10,10,35,0,26,-3,-8,-5,15,34,18,-21,-15,-16,1,20,17,1,16,8,6,-46,-40,-13,19,2,-2,9,5,-9,-30,-20,-7,-16,21,-1,-37,0,-15,5,-21,-18,-38,33,-15,-14,3,-5,-24,7,-22,-6,-36,-11,32,1,-3,-3,3,-19,27,-7,40,-17,-56,67,35,-28,-12,-57,-44,-22,24,-53,18,-58,50,23,43,65,17,-27,-70,-42,41,-62,14,-14,6,27,-24,32,43,14,7,-43,33,-1,-26,32,12,10,20,-57,-5,1,-43,36,-45,-31,-25,-6,4,15,42,8,3,32,-24,-54,51,-5,43,-17,27,-25,-35,21,-4,24,28,18,-14,-20,-28,-33,1,-26,-22,7,26,29,-1,5,0,3,24,-24,-1,22,-39,28,43,-22,34,28,-8,35,38,3,19,57,-3,-29,42,-15,-10,33,7,45,15,-15,26,-15,0,-17,-36,-42,-27,0,-7,2,-9,-17,-14,-11,9,-11,-3,-24,-26,30,20,38,6,-21,15,-7,-30,-25,-45,5,-7,28,0,-34,2,-16,-20,-13,4,-23,37,31,8,23,-8,-36,17,-18,-49,-14,-1,18,5,1,47,14,2,15,-22,-27,30,18,-27,10,18,18,31,-24,-20,9,3,-30,4,-18,-11,-47,-13,11,-31,-11,0,7,-15,5,11,-21,27,-3,-17,6,-35,7,15,-18,6,22,-11,-15,-11,0,33,-3,11,-14,-2,16,-58,14,-33,20,11,-5,6,0,22,-35,0,-15,-11,-41,33,3,-29,-4,1,31,-1,-26,10,5,15,-41,-40,-10,1,-3,29,43,-11,67,7,-14,-13,22,45,-1,-25,-28,-7,42,-2,48,18,-1,22,-57,14,17,32,17,-11,-46,16,27,-14,-52,55,3,1,48,26,-33,18,2,5,3,35,61,29,16,-52,27,13,-48,-37,22,43,19,-58,30,-1,27,11,1,-47,-56,36} +#define CONV2_PW_BIAS {61, 47, 20, -48, -33, 92, 27, 44, 10, 36, -61, 37, 30, 59, 91, 46, 77, 77, 25, 75, -19, 12, -9, -46, -57, -6, -14, -49, 54, -57, 54, 95, -12, -9, 16, 4, -51, 103, 22, 15, -5, -12, 4, 29, 38, 63, 20, 8, -30, 24, 53, -10, -7, -40, 41, -3, 2, 20, 28, 62, -87, 44, 65, -122} +#define CONV3_DS_WT {8,27,39,2,2,33,25,-26,-17,6,-13,-9,34,6,-33,6,43,-14,22,-21,-3,27,18,17,-18,22,27,2,13,14,42,-59,-10,16,14,-11,-24,7,11,15,28,-28,-18,14,-17,0,20,-20,18,35,22,-13,79,-10,-12,16,67,-14,18,6,-1,-23,21,3,-4,-26,7,-12,22,-8,9,6,22,-5,-23,-16,10,19,7,50,35,-42,-11,24,4,-25,20,-17,-23,5,-24,7,26,-7,-15,27,-18,18,-24,23,6,70,-45,-15,18,16,8,8,-25,15,18,6,-2,-6,-10,-12,-77,-11,29,26,30,-3,4,-7,-3,-21,-13,9,10,23,-11,-47,12,12,1,13,20,-4,-8,36,14,-20,0,-38,-24,1,-9,-22,22,22,-1,-19,28,13,-15,-2,19,-12,-9,4,-1,-14,-17,8,15,-52,-13,-18,-1,-15,-16,17,-32,-56,27,-2,26,20,-16,-12,-100,8,-13,19,17,-12,-7,28,10,-11,54,3,5,29,-12,10,11,22,3,27,-8,-31,-13,-9,2,5,-38,26,-36,22,-57,-17,14,11,3,5,-6,18,9,13,-7,-2,44,-19,-11,-9,-5,1,-4,-25,-28,31,9,-13,17,21,3,34,7,-13,-5,44,18,-12,-26,-15,-16,22,46,-27,21,0,-1,-8,29,19,17,-17,20,30,24,-11,25,-17,17,-3,-21,-10,30,26,7,7,12,-38,8,43,-13,13,3,-6,-14,-23,-26,9,33,15,-25,-27,-8,15,2,-22,21,42,-14,10,-2,23,1,0,-16,4,11,9,2,31,18,2,31,-13,21,7,-35,-10,16,-4,-12,-45,9,-17,11,5,8,-14,11,48,-16,-20,-32,35,-15,32,14,-18,0,-69,-14,37,-16,14,9,39,4,-24,-1,19,21,-16,10,-8,45,13,2,-17,-20,-10,11,13,-17,-15,-13,9,4,-11,-23,-23,-4,-8,38,6,-23,-17,19,-3,0,41,21,-8,-6,19,4,-3,8,-17,77,1,-35,-29,18,4,0,20,-10,33,2,11,2,17,-4,0,-40,-24,10,0,37,-42,4,-45,6,14,-38,-3,41,-27,-11,62,-17,-30,-19,34,-9,-5,10,31,-4,-13,35,3,15,22,23,-8,-47,51,26,-15,3,6,-26,19,-12,-4,33,-34,-40,21,49,18,2,-24,-46,22,2,4,23,-7,7,-3,4,-8,-6,36,33,-37,19,-12,14,30,19,-15,10,12,1,-6,-19,42,24,16,-27,12,17,7,22,-44,4,30,-13,-33,-15,33,19,6,-19,-34,-13,20,3,9,-28,22,69,-8,15,-15,-35,-14,6,-13,-16,-2,-2,-8,-27,20,-3,-13,-20,41,-37,3,-7,16,-10,6,-2,9,0,7,10,48,-22,14,-8,18,-20,14,-11,-12,2,9,14,-11,25,-13,-10,-19,-6,1,14,-7,-26,45,25,-15,7,-12,-4,1,-16,-18,23,20,-11,-7,29,-19,-27,17,-11,-16,19,18,15,-32,22,1} +#define CONV3_DS_BIAS {-44, -18, 17, -1, -31, -58, -24, 7, -7, -20, 51, -17, -38, -50, 25, 33, -11, 27, 36, -16, -35, -7, -27, 45, 36, -24, 53, -29, -93, 8, -24, 5, 51, 16, 35, 31, -16, -51, 63, -16, -11, -4, -16, -20, 56, -8, -51, 10, -13, -47, 10, 37, -12, 27, -6, -48, -21, 56, -50, -2, 39, 67, -69, -12} +#define CONV3_PW_WT {13,-2,-20,14,-10,10,6,-7,-25,3,-3,-24,-47,15,-2,25,-17,-28,1,27,28,10,-52,23,1,-12,-16,-8,2,9,25,5,-14,30,-2,-5,-4,-27,12,-6,9,24,8,-22,-7,23,-37,4,-20,-10,21,-4,9,12,6,-28,-20,-18,-9,10,19,10,14,-21,-34,6,-19,-18,-12,-12,15,-39,1,4,-65,-26,-6,15,28,22,10,-12,-56,19,5,-17,-22,33,14,-26,20,43,-11,-17,19,33,-21,11,30,28,16,-27,-35,23,-15,-36,-44,-27,-29,27,-23,-22,-35,30,36,-5,20,-4,-33,-19,-37,1,5,0,-2,22,41,-8,19,21,-12,22,-2,16,-7,-23,-23,10,23,12,3,9,-1,9,6,-44,-21,28,21,-1,7,-23,28,13,-2,-21,7,-16,-24,10,32,16,-7,-44,-25,8,-27,44,-26,24,-12,-22,-14,5,-4,-25,-56,-1,24,20,15,16,-11,19,39,50,15,11,-23,-10,-2,29,27,-21,-29,10,11,6,-11,12,-58,47,-32,23,16,43,-11,-47,31,-19,-23,16,-36,46,-3,7,87,-27,29,-20,20,46,27,-13,7,15,33,21,16,-14,9,-22,24,-59,-53,-39,-11,-8,-12,27,-9,31,6,33,-28,-34,-1,-40,22,-33,-17,-39,-58,-5,-9,-3,-25,-10,-25,-6,-19,-10,-3,-16,-11,-16,12,-12,-17,-18,-14,-9,-19,-1,1,-13,-3,-9,9,28,18,18,-1,-2,-12,36,-20,8,14,-21,-10,21,-18,-2,-28,-5,-12,19,-22,-23,-4,29,-9,9,7,4,-12,26,-5,-8,-35,-28,8,-7,13,-12,0,19,12,-42,-6,-12,35,42,16,-38,-37,-8,-11,-21,-54,-17,-12,9,-19,6,-3,3,-2,-35,21,-31,-30,-35,17,-22,41,-23,-5,-31,19,12,-32,-14,13,13,-12,-8,-44,-5,2,20,17,26,51,-24,7,42,4,-41,-38,-34,-17,-29,-38,-11,-30,-9,15,5,31,30,15,-18,4,-8,-80,37,-20,26,-24,-30,17,25,-20,27,-12,14,2,26,35,-16,-17,15,-18,-8,-6,-46,15,41,47,21,2,15,30,14,-8,10,17,-21,21,-16,-4,-14,30,6,35,-12,11,-56,-31,11,10,16,-32,47,15,26,-57,12,-5,-14,44,-31,-13,16,22,-1,29,3,-12,3,17,-26,-4,-21,6,-32,19,12,-23,-17,-17,14,-7,-24,-41,33,18,18,-47,-28,-1,30,57,28,34,25,-26,-12,-69,3,5,4,21,-14,-49,-15,-9,-10,7,18,-46,-19,2,30,39,-35,-12,3,7,34,1,-25,11,-2,3,30,-30,-26,21,-27,-65,31,16,25,-24,-16,-38,20,3,9,-15,-29,13,-17,17,-39,-39,33,-3,31,-15,-55,-49,-10,-45,-14,3,-17,10,-10,-33,-41,41,13,41,5,10,28,-35,5,-13,1,9,5,-11,-17,-9,-14,0,14,-48,9,-20,48,7,37,-6,-7,46,-4,-17,1,40,-7,28,0,24,4,-12,-8,29,-62,2,-1,3,-10,5,-15,7,9,38,-27,7,-11,-21,7,-5,23,-46,4,-5,31,-4,-2,-18,17,-25,20,9,-18,-23,15,16,38,16,-8,16,-31,17,-7,-2,1,-65,50,-14,8,-13,-3,-50,-29,-21,29,6,-22,-27,18,-1,23,-14,5,29,13,-15,38,33,-16,-37,16,18,5,-54,39,-9,15,1,12,-9,-15,-52,29,0,19,-26,-7,-45,-42,9,21,9,8,-42,21,3,-9,-10,9,-40,28,-5,0,-5,-27,-37,-18,33,21,-23,14,-16,3,-20,-19,-57,5,-32,-15,-24,2,5,-40,-17,-10,-21,8,20,2,17,11,-7,-24,-9,4,-8,42,23,-2,30,-31,-27,57,9,-25,35,19,-14,-42,25,12,3,17,-28,-1,14,12,15,6,46,9,16,11,8,-5,16,-29,-5,-9,-6,13,43,2,26,20,-40,35,41,6,-17,-26,30,-42,-6,-14,11,18,34,14,2,54,17,-1,-9,-5,2,-47,49,20,-44,18,19,2,16,-4,33,52,-6,26,3,15,-19,-16,-7,25,3,1,14,-16,14,18,-27,9,24,-31,-41,-39,-54,-32,-22,-46,15,33,-21,-30,-29,61,-69,-42,-10,32,-17,-1,-28,-41,40,-17,22,-24,-11,-25,17,21,3,-21,13,-10,-20,18,-27,27,-33,29,28,19,-23,-19,-14,-49,25,-13,3,12,-8,43,-2,-83,1,12,42,-6,34,18,-22,3,-3,13,-13,-22,-6,-20,-56,36,-40,-19,3,14,29,9,-29,36,-41,-19,-24,-16,10,11,0,-1,28,24,13,9,5,-2,-2,-28,17,-44,-43,-25,-6,-13,-30,13,22,6,7,35,-21,-20,-2,3,28,-17,-3,0,43,-35,-34,-2,16,44,-36,-15,15,-44,15,-7,50,-17,6,-25,27,9,29,17,27,-10,-29,-21,27,-6,12,3,-8,6,-22,-51,-26,-4,-21,-39,-24,18,14,-8,8,34,37,-19,-16,12,-11,-26,23,40,0,8,-35,-9,-7,26,-20,-6,-29,-32,-1,-19,-15,21,-34,6,-36,26,6,29,-16,15,28,10,-33,-15,-26,-19,-19,35,13,-8,-1,-45,-21,-9,-5,29,-9,23,17,15,-18,19,6,-37,-43,-33,7,-48,-19,13,29,-37,9,10,-35,-13,18,19,19,25,27,42,-2,18,-31,10,-29,8,-42,19,-20,-31,-48,17,45,-2,49,-30,3,-18,36,8,14,23,-8,-26,-17,26,34,-27,-2,-32,-16,9,2,-26,-3,-8,-57,11,18,34,5,-42,-1,10,58,60,10,-24,11,4,-2,-59,-22,-13,50,20,-25,-49,47,47,18,10,5,-32,-4,45,-48,22,-37,29,-18,22,43,-9,10,-26,13,28,-8,-23,-18,4,13,-1,-12,-3,-8,31,24,-8,-14,52,74,34,-18,-10,-17,-12,-12,17,1,-26,-13,-10,-34,0,6,10,23,29,14,30,0,-3,27,37,0,13,-29,2,9,42,3,-45,35,-55,-22,11,-54,-12,-23,9,-13,6,-5,-2,40,-8,0,-2,-42,-22,19,-10,13,-48,21,-15,-4,-36,-35,9,-49,9,-59,-20,38,-9,-19,-6,-7,30,-36,-19,14,33,-12,46,0,17,36,14,-21,-12,-13,-13,10,41,1,-36,17,31,-24,1,-25,4,33,3,-7,18,9,33,-26,6,11,-58,-1,34,-53,-2,5,-13,29,19,46,-6,-14,29,-38,-18,-33,4,-26,35,-5,-32,-25,3,-25,-37,-40,3,-34,19,-39,19,-18,-9,10,1,-49,9,-6,-19,43,-14,20,-7,20,43,-27,28,-7,44,17,15,-24,-8,10,19,-20,-3,5,-18,-24,18,5,-18,-61,-37,2,24,41,-61,38,42,3,-19,-7,-36,23,-1,17,1,37,29,-10,-6,-36,25,22,-8,-61,1,9,31,13,10,14,22,-15,-21,-10,9,15,27,10,18,-7,-32,21,-50,17,-44,3,-1,19,9,-57,59,31,20,36,5,-37,-46,14,-10,-39,-5,24,4,-27,7,13,-40,-23,-26,-6,21,-10,0,7,-16,-12,8,11,-17,-24,20,-20,16,-32,-8,-14,-18,-32,-15,-38,-24,1,-6,5,-10,-11,5,16,17,4,13,3,17,-4,-28,-1,-12,-7,-6,6,-22,-2,6,-1,7,-17,-36,-16,17,2,-12,-21,10,-28,-4,-30,20,-24,-2,2,-37,4,15,6,30,-13,-3,7,13,-71,-17,-9,0,-23,4,9,-21,26,18,18,-37,7,90,20,-25,41,36,48,15,-11,8,7,19,25,-2,-44,22,15,-17,-9,-12,-14,39,-7,39,46,7,-22,10,4,32,-15,-13,14,-3,47,-10,2,23,-19,-14,-21,-7,3,9,17,35,-26,-17,14,-14,24,6,-39,0,14,-31,-36,-15,0,-30,-34,-16,-22,14,9,22,57,39,-33,-11,-49,21,15,44,1,-22,-45,-22,-31,38,-17,-23,-23,29,30,-38,34,36,-18,-10,-6,-21,6,6,-36,-58,27,-42,-20,-45,50,6,25,36,22,4,32,23,-45,15,35,-20,20,-6,-30,19,1,-3,-24,46,8,-2,-17,10,-29,9,33,-51,-7,-36,42,16,-8,-12,35,-16,-23,7,27,-34,-51,48,56,-37,57,-14,0,-45,45,0,33,2,37,11,17,-54,1,-39,-18,-1,10,-13,-20,6,25,28,-18,28,10,-26,-32,-8,-9,-18,12,-14,24,-2,21,17,4,26,-24,-8,39,-22,6,7,10,-34,1,-15,-30,2,-36,-37,-46,12,-17,2,0,3,8,-36,-2,25,-43,37,-26,20,31,26,20,32,-3,10,-39,-18,-4,-8,3,17,-12,-51,2,20,47,-49,30,-44,0,-24,6,-2,23,-33,-17,25,29,23,12,-18,11,-29,9,23,20,-24,-13,0,48,-21,-30,-5,43,-20,25,18,19,15,34,21,-20,-8,12,-49,16,33,-45,8,38,25,-8,-6,-19,18,-13,45,-16,-46,14,-4,-14,3,39,-6,15,-22,37,-3,17,-52,-33,4,29,23,-3,-22,12,-60,15,32,22,-19,-38,-61,-6,-25,12,-12,-12,-19,17,34,25,-13,-24,4,-19,-3,22,5,65,30,18,24,26,0,-6,38,45,10,-22,-35,5,-23,60,-72,24,42,8,-22,41,-25,6,37,7,15,-37,-18,2,31,-31,-7,23,21,-11,37,-15,18,-15,0,3,38,0,-21,-15,24,9,1,3,-2,21,10,5,-34,48,-12,-7,-40,17,-42,28,1,15,-36,8,-25,23,-16,1,-26,40,28,-28,-9,-19,20,-5,-26,-33,22,-49,44,-19,45,-27,5,-20,-30,-56,10,41,-3,-19,-12,-4,14,-40,21,2,1,4,0,-29,-24,-34,22,-24,37,-31,-15,-15,-8,10,12,-29,-7,-38,-22,-6,4,-24,-45,-15,22,40,-37,-27,1,-14,-29,15,-2,24,-21,26,-6,24,-9,0,-19,23,11,-13,4,-1,-22,3,6,21,-43,13,-18,-39,-2,26,-8,8,-14,8,4,-38,28,-20,57,-12,-13,-57,-6,-5,36,-5,-7,51,53,34,12,27,-28,24,-23,18,32,-30,29,-23,22,52,33,1,16,-49,-8,-12,24,18,-22,-76,-40,-29,-38,14,-49,-39,-55,-46,-14,-17,-46,63,1,-18,-38,3,2,9,-21,28,-15,-19,-8,-9,22,-43,30,23,-20,-22,14,17,-29,1,5,10,-6,25,-19,-38,-6,3,-2,-21,4,-45,-15,8,12,48,19,-67,-5,-26,-6,8,-28,28,8,5,-51,-13,22,-49,11,-85,7,13,-25,-30,-3,31,-7,50,27,-3,-56,12,18,-16,5,-5,-76,47,-12,-28,63,13,-29,-26,33,0,-2,-1,-8,6,-16,20,-8,-27,-2,17,-11,10,-23,31,23,-38,-6,24,17,12,-5,-3,14,22,-10,0,29,-24,28,39,-7,28,24,29,-28,-39,-39,-36,22,-25,-28,-4,-14,-7,-11,14,-23,8,-8,28,5,1,-6,9,14,29,-16,12,27,31,-15,-23,-26,6,24,-18,-1,44,6,15,2,4,1,-19,2,17,13,-7,-28,19,-15,42,-31,-1,20,6,26,-14,36,8,1,8,-3,50,17,-3,-51,-34,-1,3,-13,23,29,37,-7,17,-16,-1,-31,-29,22,9,7,10,-46,-24,-38,-24,-41,-9,-3,45,15,28,64,-12,40,19,18,-35,6,-5,29,-3,-31,11,33,28,29,3,-46,15,39,-50,13,3,-11,-1,36,-57,-38,17,32,-19,13,7,39,-35,13,-23,35,-21,0,-53,5,-36,48,-8,-12,-31,-13,-2,-8,-31,12,0,-26,25,-20,4,-18,33,3,-29,31,-22,-25,-23,14,12,-1,-14,-17,-26,-23,-3,15,-27,-7,9,5,1,14,26,-7,-7,15,34,29,-48,6,-1,22,-22,-5,16,29,-37,12,-11,-10,22,-15,34,-36,18,10,24,-43,-7,-19,25,-8,-22,29,-25,-16,-24,-3,-11,-5,-33,38,28,-22,-22,12,-21,17,28,14,-30,15,31,-35,-5,-29,-38,10,38,-20,-10,7,-4,-38,23,26,36,2,-21,41,-20,17,-35,-4,-21,28,-31,6,9,-15,-27,-34,-9,18,-37,-2,-6,-32,-29,8,-23,-32,25,-46,1,23,-26,-28,17,48,11,-18,0,-29,21,5,1,1,5,-8,-43,-8,25,-42,-4,-5,-3,22,9,9,4,-5,-6,45,-39,-12,-3,-5,25,21,15,-29,12,-21,-15,3,-39,-4,-41,-43,21,45,-1,28,20,9,2,-43,-35,14,13,-7,-38,35,0,-5,20,-41,-65,-5,-24,-24,-4,-21,10,10,29,8,18,-13,-7,-30,-19,-21,36,-30,-21,-2,11,-8,0,17,-21,-7,-5,-16,-2,0,-29,9,46,11,-26,34,1,19,-46,-20,-15,-18,-13,-1,-2,-3,25,43,-32,-18,-19,-4,37,15,8,-40,-31,-3,-31,12,-18,-23,-12,-60,13,30,8,-22,9,9,-3,16,-2,-9,25,-7,-39,-30,5,11,-19,7,-32,-5,36,-5,18,32,7,50,-46,-13,21,34,-27,-20,23,16,-5,11,10,-16,-36,37,12,30,17,6,6,37,6,-2,-21,0,-2,-68,-4,-27,59,-3,-4,6,26,6,37,-3,31,25,29,-12,1,31,-7,-20,-7,32,-26,-2,-15,-31,-34,9,-8,39,-20,9,-6,-12,-18,-18,-4,-3,-23,0,-1,35,-26,-13,-7,17,-14,34,-13,3,17,18,12,50,50,-6,-12,3,-26,-32,0,18,-9,7,21,25,46,35,40,48,20,-15,43,-9,-10,37,-6,11,14,-6,31,-49,-4,-67,-19,-1,21,22,-17,-7,-9,-22,0,1,-37,0,2,27,43,-18,21,-29,7,8,-3,8,-13,-21,-18,10,13,-33,-7,-23,12,8,-50,-31,3,-50,55,42,11,-21,3,-16,22,-10,-22,36,-11,-4,3,-4,-9,-9,-11,-39,31,-13,35,20,8,-14,-7,-21,-24,27,-16,-28,-31,-1,5,-20,-18,-31,24,27,16,19,-18,-13,3,-19,-1,-31,3,-2,-13,-2,-25,36,32,31,-22,21,-2,-10,-15,-17,29,6,30,26,9,-19,-32,-41,19,27,4,8,-14,-21,-3,-47,28,-18,24,-40,-5,-36,30,14,-7,-37,-3,-12,38,17,32,1,9,-6,-4,-47,-28,0,-38,-49,-4,-7,-13,5,22,-5,-40,-10,-16,29,55,18,8,-2,0,-2,-5,-36,-9,17,14,-1,15,46,-5,4,-43,11,-2,-7,-29,26,30,21,32,11,0,-23,35,39,-30,0,8,20,-7,-40,-23,-9,-10,-1,-18,5,-27,-22,-21,-8,-4,-42,26,-14,24,-9,29,-52,50,35,14,-14,14,-8,20,-11,-7,-28,25,-3,20,-16,-8,4,-2,46,-29,30,12,-23,-56,39,34,-5,-24,-5,-30,54,-15,13,22,-23,-3,9,-29,-5,15,-12,-45,-49,10,-6,20,-39,11,-5,18,10,-6,31,2,5,36,-3,-15,-17,-17,-31,48,17,-2,25,-36,43,-43,-10,-18,41,36,-20,1,22,26,5,2,9,7,15,-2,7,-32,17,1,30,-17,0,-1,10,5,2,-37,-36,23,-39,-18,-10,-45,23,7,32,22,34,48,27,-67,-56,-23,-13,11,8,-19,-12,18,-10,10,-1,-21,-5,-15,4,22,-23,24,0,-22,-15,-14,-69,-45,50,27,-18,13,36,7,-35,-43,-3,-13,2,-36,18,12,0,-30,-57,49,12,-2,-16,-49,-4,12,30,46,-23,3,19,21,-38,-1,-3,8,-33,-29,25,61,-1,-5,15,-43,3,-14,-19,-19,-19,7,17,42,26,14,28,-27,-30,-15,-21,30,-6,-32,10,18,-18,-18,-17,-7,39,11,3,-7,-13,-23,-10,23,-16,-12,20,19,-1,-8,5,9,22,37,29,-19,-35,-8,-19,-7,-36,-5,-9,-28,6,22,-11,-20,18,13,0,11,-5,-1,-6,31,-4,-37,-22,30,1,-30,-22,-13,-40,28,-47,-31,1,9,7,-36,-5,-13,14,12,26,-46,-12,23,17,46,4,50,27,57,-9,10,26,23,-58,-82,-47,8,10,-3,-4,46,9,-8,-13,-44,-22,0,10,-23,-47,-23,-7,41,54,43,-42,-51,21,1,-9,1,36,-50,6,-3,30,-30,7,-3,13,-32,13,0,-7,8,-57,-17,-10,-13,-44,-4,23,0,2,6,22,16,-31,-5,-27,-18,-30,-1,-7,-22,-17,-20,6,22,16,15,18,-13,26,-8,-2,6,1,1,-25,33,27,-33,-4,9,-2,13,-13,11,-16,24,-31,-53,-38,-10,20,-21,-30,20,-16,44,-39,19,7,0,6,30,-18,2,-17,17,8,-11,7,-22,-1,-19,7,-40,-9,2,-8,36,-18,19,32,11,9,29,-7,-10,4,-20,75,23,34,12,1,4,-9,10,33,-2,20,-8,-35,1,33,34,-14,-31,0,0,3,-25,20,35,18,23,0,24,0,15,-15,20,-22,-11,9,-12,28,7,-3,21,-11,-26,-24,14,-24,3,43,13,36,19,6,-13,-38,-21,17,-19,6,1,-33,23,43,-25,-5,-24,-50,-25,-4,-33,-6,-32,-32,11,0,16,-3,23,14,27,17,-7,-5,-3,22,-15,47,10,6,4,9,40,-5,17,-7,-10,-17,-3,-4,21,25,-72,-5,-10,31,-14,-11,-28,-71,26,-7,-51,29,29,4,17,-12,-41,10,15,-6,2,-3,-28,-40,29,22,14,-27,5,-10,34,-3,-13,-32,16,40,-26,8,18,-2,-14,29,-5,20,15,3,6,-30,-29,-16,11,-17,-22,10,41,-7,0,-21,-25,-11,-45,-8,-5,-31,3,-21,25,-36,10,-39,4,-38,18,11,-24,27,4,18,10,-26,13,25,12,20,5,20,-16,-18,-2,34,-21,-15,-30,20,-20,-33,9,26,27,-42,-9,-6,-19,-5,-16,23,-26,37,-3,-5,5,-13,9,16,-46,54,29,26,-54,29,-12,-9,-30,6,1,-16,-17,-61,-39,23,-13,-39,-5,13,11,25,2,-1,2,22,-27,-38,-9,5,-17,33,33,-21,-20,-44,0,-14,3,-28,-6,31,0,10,7,20,-15,-42,-41,14,38,12,-7,-22,-33,-13,14,30,-10,23,-20,42,8,-5,-45,3,-44,-7,13,-9,21,25,-5,2,-2,-4,-27,44,-15,3,6,-19,52,30,-9,-19,23,19,-6,-13,40,-2,25,10,-6,1,-8,-37,-6,-12,-15,5,1,-2,23,-48,40,27,12,-30,8,-14,22,-9,-26,-4,-45,-7,-23,-4,-27,13,-5,-33,-8,-13,-9,39,-23,-18,17,3,-25,35,-8,14,14,21,8,-6,17,-41,-16,1,-27,-36,-29,32,23,-31,23,29,24,-24,-16,16,21,-15,32,-30,-40,-6,26,-14,9,-28,-7,-18,-5,26,-12,-31,-2,14,42,53,6,-19,35,-3,18,68,-10,34,-40,11,39,20,-15,-22,42,-37,13,-13,-16,50,-4,10,31,-33,37,7,-29,-6,-4,-13,-21,4,-17,25,-27,0,-54,-33,-24,42,42,-14,36,-16,-26,16,-17,-47,3,1,-16,21,-33,-44,-48,29,-6,-36,-6,27,14,42,1,-15,26,26,7,-12,-14,2,-10,7,-16,7,16,-23,17,-11,-6,13,2,18,-23,24,-10,34,-39,-27,34,25,-2,47,-28,10,-40,-63,18,-13,-17,4,-20,18,-16,-13,20,24,-34,31,-40,-9,-20,-21,15,18,-16,-41,-5,-24,-21,15,-41,-3,-14,34,3,17,34,-38,-46,-9,34,-40,-32,-5,-29,-14,-50,15,-5,-4,7,19,-5,38,13,17,-31,9,6,-3,-3,30,23,0,-27,1,23,32,9,-44,-25,-37,-13,24,-13,32,-22,25,-18,6,-14,-27,39,12,-37,-37,-23,-20,-18,-33,6,16,-1,-12,10,7,-4,-7,17,1,37,-4,24,37,-61,5,-1,4,-17,13,11,-4,11,10,34,12,-9,-24,34,-12,64,43,14,-35,30,-10,12,-66,12,-37,-20,-30,-45,-17,-3,43,-21,25,3,-11,-46,4,-4,-37,-17,4,19,-56,10,-30,58,-6,24,16,17,-17,-48,2,-18,-13,-24,-9,-32,43,11,-17,15,24,45,32,-26,-24,-23,15,-25,-13,-47,-2,-2,33,-46,-37,-15,25,20,26,77,16,41,38,30,2,-14,-15,-2,15,-14,-41,-23,-13,13,49,-7,36,29,93,10,14,8,-35,48,22,41,-2,26,15,15,37,-2,24,11,24,6,-36,32,8,-55,-46,8,-29,0,-22,41,-2,-24,-10,27,37,-8,-29,1,-25,-5,0,15,-3,-16,18,-73,-25,-9,21,18,9,-1,3,-36,7,-67,30,14,-2,-16,-4,-15,-18,16,13,-53,9,6,58,-26,31,5,21,-8,3,23,-10,25,-9,-1,-8,9,44,47,38,-29,-2,43,4,-50,9,11,-14,-22,-26,17,-8,-44,15,9,0,-24,25,-34,-14,0,-5,16,-40,-32,-46,-8,-14,32,28,-27,-42,62,31,23,-22,67,-12,12,-41,36,-17,15,12,-20,31,-16,39,9,-21,18,36,-9,23,28,-39,12,-20,40,13,-28,-13,58,58,-53,32,-19,2,-7,6,-10,13,3,33,-12,-14,39,38,-22,-43,-16,-2,35,-9,-25,18,8,6,-13,19,-28,-2,-24,9,-16,-30,-44,0,19,-18,9,-5,-31,-7,8,-32,-15,7,28,-18,14,-2,10,-34,-38,-22,20,-15,39,1} +#define CONV3_PW_BIAS {15, 29, -19, 12, 44, 41, -17, 33, 26, 9, 70, -70, 36, 26, 1, 63, -18, -52, 45, 16, -20, 90, -29, 24, -14, 10, -32, -32, -1, 57, 39, 41, -26, -28, 29, 9, 59, 42, 35, -40, -60, 35, 32, -22, 9, 8, 9, 14, 25, 35, -61, 37, 6, 17, 20, 23, -3, 14, 57, 7, -65, 23, -23, 3} +#define CONV4_DS_WT {86,55,-9,37,-14,55,24,48,41,47,60,54,37,-20,-41,17,8,-30,8,41,53,-93,-5,25,18,55,60,43,62,-56,-3,0,-21,34,54,10,65,-48,33,-15,-51,-70,-57,0,-17,33,12,25,50,-45,-18,21,49,34,34,62,-51,21,-71,41,19,15,-11,24,3,-2,-44,25,-38,-27,2,51,38,-44,-23,57,28,46,62,46,-24,-46,-25,23,45,-54,73,2,-21,-22,-52,32,-34,39,-17,2,-38,3,14,37,5,14,45,-24,-32,-12,-22,18,-9,64,8,-16,-5,-3,25,2,29,-10,-8,-40,-34,35,-10,5,33,39,-35,-51,-86,45,-42,25,3,69,0,12,18,-23,-28,8,10,5,36,8,2,17,14,-3,-5,0,-41,-5,-53,8,14,7,-48,33,-68,31,0,27,31,-20,38,-27,44,-18,39,-22,-1,24,-47,42,-26,-19,48,-34,-28,17,85,27,43,-55,-14,-72,-29,39,5,5,-24,40,31,34,-27,30,-45,40,36,18,26,-38,49,40,26,-20,-50,19,26,-13,67,13,33,-44,-30,48,19,46,0,42,49,-47,22,26,-22,38,23,74,34,-49,40,-14,-29,-45,-43,22,-5,1,32,5,52,-38,-25,17,51,50,7,46,-7,-18,-23,30,13,13,-9,33,0,21,-37,36,-64,39,0,-13,29,-21,-19,-14,8,45,66,25,17,-11,11,19,42,-25,13,7,-35,12,-21,5,-15,15,-23,2,-25,-19,16,6,-3,-12,27,-13,-32,-20,-14,-30,-14,42,-14,-40,7,3,9,16,55,-13,-35,-13,-15,33,5,-10,-1,20,-35,1,-59,20,2,14,-25,39,0,31,10,-12,-55,0,22,10,-40,-5,20,10,0,36,5,-19,31,-2,6,47,12,6,-1,26,-29,31,7,31,8,-28,25,0,40,-18,29,-38,-18,15,-33,20,-29,-22,46,-56,-33,25,49,4,9,53,-30,-38,-25,31,22,33,20,56,34,35,-35,36,-78,32,26,26,39,-39,13,-31,11,-19,17,35,64,-40,70,31,23,-23,-21,52,37,35,-37,19,47,-38,45,100,-40,26,23,38,22,-54,14,-45,-6,-16,-69,63,2,-48,33,-10,11,-11,-32,21,17,59,27,69,29,-24,-40,26,39,3,-16,64,-67,6,-14,21,-68,43,20,-37,17,-27,-33,-18,29,50,56,38,23,12,-32,18,20,-11,9,13,-13,21,-36,13,-24,24,-2,24,-20,-30,26,77,5,25,-81,-23,-13,-43,-35,-71,-14,-26,-30,-34,13,-6,6,-1,39,-7,-40,-11,-8,68,-8,0,17,15,-28,18,29,12,-9,22,3,55,9,33,14,-63,-51,1,6,-23,-5,6,29,26,18,26,17,-18,81,-18,44,82,-3,20,14,42,11,40,3,-8,-2,31,36,-14,69,-15,43,-19,-34,7,-42,-39,-25,-82,35,-24,-34,38,-43,43,14,101,-20,8,-45,15,27,20,12,67} +#define CONV4_DS_BIAS {-1, -50, 70, -74, 95, -72, -40, -40, -74, 66, 23, -27, -56, -39, -41, -57, -49, 29, -36, -57, -53, 90, -46, -32, -1, -64, 22, -46, -20, -24, 15, -47, 58, -23, -69, -63, -55, 52, -68, 57, 19, 81, 81, -1, 64, -24, 20, 58, -64, 76, 33, -50, -73, -46, -1, -36, 42, -27, 82, -53, -53, -46, 43, -56} +#define CONV4_PW_WT {-38,-20,38,15,-16,1,-5,-25,-21,-1,-7,21,13,-12,-33,-12,-13,-21,-11,14,21,-18,15,4,26,11,-16,43,-16,2,-15,-4,-8,-45,19,46,15,20,-5,-7,17,-31,31,7,-23,13,-32,-6,-7,-17,5,47,20,-50,4,-11,12,-17,1,-28,27,20,-10,-31,-6,39,-8,30,12,3,-5,7,-19,-12,12,-36,0,-1,31,16,-9,-18,-25,9,13,17,-5,-12,-3,33,44,-34,-15,-14,-4,-16,2,16,-60,-2,-52,-19,-16,16,34,-23,44,-13,-11,1,-43,11,15,-59,21,-16,28,-1,-19,11,19,-3,18,17,-16,15,34,12,31,-25,0,-28,2,-5,31,-28,-25,30,-32,-12,6,15,-53,43,-23,-36,10,-26,2,-22,-6,28,-1,39,-27,35,52,49,37,23,-38,-15,23,37,-7,-2,-36,44,-15,-34,27,-1,28,6,-31,29,21,7,48,0,-31,-16,-26,-59,13,-9,46,-3,-30,5,-34,25,25,10,-26,-11,-19,1,-33,1,-31,-52,11,-55,29,26,-16,10,-8,-15,18,-9,18,-15,-22,24,-14,-36,-50,-16,-55,30,-16,13,-6,20,24,-2,-33,8,-8,-14,41,9,29,-7,11,13,-45,15,-20,54,-15,19,-52,-5,-7,-3,-36,0,5,-33,-6,4,39,3,12,8,-92,-49,-14,8,-24,-4,-10,25,1,-16,28,30,-39,-14,-10,22,-32,2,-2,-27,-27,-1,-19,1,-9,0,-29,25,-19,43,1,25,-8,-9,-52,4,5,19,-26,20,33,-1,4,-6,-21,40,-7,11,37,-15,14,2,-25,2,-43,37,11,25,-6,41,2,-32,-16,-10,3,-43,-2,0,-16,22,3,-32,-35,-36,-2,47,13,2,-7,-27,-18,-5,-17,-27,-30,4,-10,7,-50,-27,-37,13,4,18,-40,19,35,2,-19,4,15,-38,1,15,-7,-30,59,9,5,12,18,55,45,11,-3,33,-27,-7,-14,-1,-1,-16,-38,-23,1,28,-20,22,-34,-32,17,-31,-43,-27,-9,3,6,-39,-14,15,-40,-5,-31,-19,-31,45,4,23,31,35,34,-43,36,-15,24,16,-44,40,0,-6,-48,12,3,28,-9,35,-32,-7,-37,19,-23,-1,9,0,-30,-37,6,23,-22,-13,17,-8,-25,-20,29,-18,-20,17,-32,-4,-2,20,-6,-28,10,-21,-25,-5,-36,-10,19,-29,19,20,-3,-44,-54,-41,13,-9,-13,13,-12,9,-1,-4,-21,-16,-43,45,3,-40,-22,11,13,-9,1,-24,-8,35,-8,-13,2,19,-28,-17,-16,-4,5,13,-15,32,-11,-17,-11,2,5,29,1,-19,3,17,20,-2,18,58,0,-40,-11,60,19,40,30,-14,16,9,35,15,1,-56,25,11,-9,-13,7,28,54,7,28,-1,-38,-15,24,34,-17,-24,11,-33,-6,24,-22,19,9,-18,53,-41,23,24,31,45,-1,-23,26,12,-51,-57,-38,-23,-3,-31,-4,-19,-43,-8,7,-22,32,-14,-26,-18,25,-15,-10,16,-15,18,-19,-45,16,-30,23,21,-14,28,-41,-25,-31,-32,19,-15,-33,-18,3,15,-25,-6,-2,-14,-9,-9,-4,26,32,4,9,-42,13,-21,23,23,-16,-7,-30,4,-60,-6,-8,-3,-24,13,-39,-13,-32,32,16,-28,-2,-28,-33,7,30,34,-21,17,-29,2,10,30,22,5,-26,-32,6,-14,-18,-18,-56,16,-24,-52,-24,-4,23,31,-22,-16,-33,37,-35,14,10,-6,-44,-2,-26,0,7,0,-59,-36,-34,46,-22,-1,17,-6,-19,-3,-36,2,-16,-5,-19,-14,-31,-3,-5,8,57,20,-11,-12,-30,-22,49,18,34,21,19,-5,-42,31,-15,-8,24,12,7,33,-40,-7,3,-21,27,-5,1,-5,7,-2,1,-1,4,-22,1,-36,-49,-64,9,-26,21,2,-30,-15,-27,-2,4,-6,5,15,22,-8,3,-19,3,-30,6,1,14,-36,-36,9,6,7,2,-42,11,24,-29,10,-5,35,23,1,17,-16,22,30,5,20,-5,-36,16,-18,35,-37,-23,25,37,-46,18,27,34,17,-50,-30,-7,16,-8,15,58,-21,32,-19,-15,-15,-26,37,-12,0,-8,-3,0,12,-10,-39,-36,50,-6,0,7,-19,44,2,-1,50,5,-2,-38,-1,30,33,-21,-27,27,15,-37,10,0,31,14,23,-4,16,-2,-13,16,11,0,6,-14,24,2,46,-11,-45,-39,-44,-16,-15,-12,-22,19,14,42,13,7,-9,20,6,-28,47,41,31,-19,7,-32,-20,4,-3,-24,-20,38,19,2,14,4,31,-29,6,-16,11,16,9,-17,-22,12,-33,-33,30,-7,28,-27,1,-16,9,29,31,-18,-22,43,-22,-16,14,-14,27,14,-3,-3,-8,3,26,-7,17,14,8,38,13,8,16,1,-8,-25,-9,-1,15,9,-16,38,20,5,5,24,8,12,-14,3,-3,33,-17,-22,20,16,2,13,-7,-6,10,6,-7,-29,11,6,26,23,3,-15,-16,4,-22,-16,31,-16,-3,-18,-29,9,9,-19,16,12,1,-1,22,-22,12,-49,23,35,13,21,-34,30,-9,-13,23,-45,-13,-12,-8,-9,25,21,56,27,36,-14,4,8,14,25,4,-12,-20,-15,-9,39,28,-32,7,27,3,63,-2,4,-8,19,1,18,11,-23,-10,-1,22,17,-28,20,-54,48,16,-22,20,10,-19,-5,-42,-40,-14,5,59,29,-23,-40,14,-22,26,3,52,-4,15,-30,-1,-36,19,14,-79,-55,8,35,33,1,-18,-13,-2,-39,-24,8,2,-14,-26,14,31,-61,24,67,18,-37,-21,-44,37,32,22,4,1,-11,-35,13,0,-9,15,6,-28,2,-5,9,31,-39,-17,8,5,-38,-6,11,8,4,13,2,-28,-16,-61,7,3,47,-40,-35,1,21,-24,24,-52,-7,-12,4,-15,4,18,24,21,-15,-71,13,26,-27,17,-42,2,-16,-3,18,-16,19,-28,-26,-33,35,-7,15,9,-13,-17,43,-1,19,-1,-1,-37,-14,-37,-13,18,-18,-42,-1,1,-5,-27,-20,-21,24,51,14,-26,4,-9,-43,15,63,-15,-43,-17,5,-8,-36,33,5,39,47,-12,-21,8,-17,25,24,-12,-28,26,-52,-34,-40,-3,-46,-12,-6,34,-3,3,-24,8,-16,-22,-13,-49,21,16,8,-6,14,-4,-20,6,7,-19,-9,-20,-29,9,-26,38,-5,5,10,3,-13,2,-19,-4,-27,17,5,9,29,-7,17,20,17,9,-2,10,-7,-7,-6,-11,23,-17,-24,22,-31,-13,-7,19,-5,-15,-33,-19,19,-24,39,-19,-27,-7,-16,-24,13,-12,-39,13,-67,27,3,-38,0,-45,8,-12,-2,3,5,10,-37,-30,-36,7,-31,-6,5,3,0,-9,15,6,35,-14,-6,3,-42,13,-49,-37,-5,6,-30,29,-26,11,-3,46,31,-3,-44,30,1,-23,-51,-1,6,-4,14,-4,-29,15,30,-37,0,-33,-22,10,-12,13,3,-37,19,-9,6,-16,3,-23,0,-22,18,7,-28,13,2,-5,3,5,3,-4,13,-23,4,-2,13,-2,0,-7,8,6,-21,-37,4,5,-11,17,10,-1,-14,-7,13,4,11,-21,1,-18,-12,-8,-27,5,16,10,-9,-3,-7,-10,-7,-1,11,5,-19,-29,-2,2,-6,-2,25,33,-6,5,-6,11,13,-8,14,14,29,10,4,8,36,-20,-1,-1,-10,19,15,-4,-7,-14,-4,13,16,4,-3,17,42,11,10,5,5,-16,13,37,-11,31,20,-8,7,41,-20,-9,12,-19,32,-11,-2,16,38,-14,18,1,-19,9,34,-14,25,19,29,-21,-15,-21,-20,19,-29,-3,-29,-11,-4,-3,5,-12,6,-24,-3,7,42,-7,-61,1,-23,25,-5,0,2,-23,39,-38,3,15,32,-9,-17,-5,7,-12,-16,-7,2,-4,25,14,16,27,5,-43,36,-1,-14,-18,-45,10,-13,-43,-7,-20,13,-30,20,6,22,12,-20,24,-33,-35,4,-7,2,-11,-5,16,31,-29,3,38,-4,-16,-24,-25,13,3,-27,13,2,-9,-58,-11,-50,-13,18,14,-21,-46,-32,35,-2,-12,-22,-43,-5,2,-21,-5,14,37,24,21,-1,-68,33,19,20,-39,-14,-6,10,-7,-6,-6,-24,-4,-27,24,-3,28,-7,-14,-19,-1,17,-10,-11,-2,-18,-9,3,-4,1,-9,-15,-8,-39,4,-1,-8,-2,15,-29,-26,-16,-12,9,-27,1,-11,23,-25,9,-10,-6,-1,8,4,24,4,25,-6,0,4,-14,-3,-10,-15,16,-17,-17,-7,33,-4,6,10,10,16,-30,-15,-48,-3,0,7,27,-26,40,-17,13,-12,0,0,-38,-13,-15,10,-7,4,8,-4,-4,-3,-36,19,7,15,0,-24,9,10,17,24,27,33,35,5,31,2,-27,10,-35,10,-18,-4,-19,-27,-6,-30,-12,-24,9,-10,-12,-5,25,6,-44,-36,24,26,-39,29,6,3,-8,-10,-15,-7,-24,59,5,17,3,8,-24,-25,-17,-10,12,-7,-2,1,3,-26,14,38,29,10,26,39,10,23,-9,34,51,10,10,10,-18,-18,2,25,-39,9,11,-1,-32,24,2,8,-18,14,10,-22,-15,22,1,-4,-18,9,50,-7,-22,-40,-4,65,-7,46,26,21,-4,27,41,15,-59,-12,0,-16,-26,8,-68,-25,0,15,35,-26,-11,-50,18,-9,15,16,6,23,22,12,-17,27,-36,18,-42,49,-39,-10,13,-28,30,-33,-33,20,-28,63,13,-43,3,36,-72,9,-55,40,-20,16,6,-9,-46,-24,-14,-30,-6,41,-12,-31,-12,-1,-9,6,-10,26,-37,-11,20,-29,-14,21,-37,-28,-3,-41,-1,45,37,24,11,51,-23,-7,42,-11,-4,-8,7,13,-27,10,-47,11,21,10,-35,31,19,16,3,0,-13,18,26,-7,20,17,26,-43,-3,3,2,58,-6,27,-45,-40,98,-2,0,-38,35,20,-24,12,-40,26,-10,4,10,-39,8,14,21,28,4,-28,-3,-10,27,-4,-1,-25,-51,-14,-18,-8,-21,42,-22,-12,10,35,-13,-14,9,10,-3,-4,-48,-40,11,-14,2,9,-3,6,-20,12,-26,2,-44,-37,-16,32,-34,22,-40,-21,18,8,-26,-26,8,-15,-6,-36,19,-8,-6,-33,-28,13,-26,2,-8,-15,11,-45,16,-46,43,4,-40,0,24,60,-1,-3,6,-35,22,21,-32,9,34,-27,32,35,-24,-52,-23,-28,-14,-21,38,-7,-18,19,50,23,19,29,16,-15,-11,19,-25,-76,42,16,8,-23,4,35,50,5,-7,-14,-15,41,-18,-40,8,-34,28,57,5,19,-1,32,0,-43,-4,-10,-7,4,-7,8,18,0,25,21,-2,44,23,11,2,11,-6,14,6,-60,21,12,-23,17,-12,11,-35,-14,-7,-6,-21,34,-2,27,34,-10,1,-13,-14,10,-31,-30,21,19,-19,9,-30,5,21,-3,2,23,-10,18,-15,15,7,-22,0,-12,31,-30,0,-23,-15,-2,13,-2,-19,-3,3,2,-5,3,8,-24,-11,-20,-4,11,9,6,-4,17,-2,-5,-15,-16,7,1,-12,7,12,13,-6,-5,1,-3,-2,-13,3,-9,16,12,-25,-27,22,-2,-11,1,-16,1,-7,0,2,-17,-32,-13,-3,-15,-3,14,11,-14,31,15,-30,24,-25,-41,-4,-20,10,8,-8,7,9,-20,-10,-12,-30,25,-14,-15,-17,35,31,-20,-5,13,-11,-26,16,10,-6,11,7,-32,-35,0,3,7,16,34,2,-7,-51,14,-15,9,-17,-19,-31,13,-8,-32,0,18,25,-30,-15,11,42,30,3,6,-44,-5,5,-21,-11,17,-39,-7,26,-1,7,26,-12,4,-32,-35,34,44,-8,13,11,26,-28,25,-9,-14,-13,38,-28,-14,-52,3,-25,8,-12,7,46,18,3,2,34,25,-30,-52,1,-36,-15,20,-18,32,3,26,-18,30,7,12,21,-48,-21,8,2,22,18,10,28,-19,-38,10,-36,-9,-3,-12,-51,23,4,-2,12,-8,-4,-33,11,32,-25,22,-56,-67,-21,-24,-17,-5,-6,-24,21,-28,-42,-6,-30,-9,0,-33,26,-17,11,8,-8,-20,-38,39,22,47,28,3,3,-8,-23,-8,27,29,-14,-32,-19,28,-26,12,13,13,10,41,-7,-39,-19,-27,-1,13,-6,6,18,5,-46,-27,-20,2,-4,16,-18,25,1,-9,19,2,-14,13,22,-23,-10,-15,26,-30,-9,8,-48,14,0,4,-3,10,10,-25,9,-21,18,-20,-30,-40,-14,8,21,1,-5,29,15,-41,1,0,31,-27,14,-4,-47,-20,-71,4,-18,11,-2,-46,9,25,-14,5,53,-5,7,29,25,7,-12,7,4,-3,25,-24,8,-32,-20,56,0,19,9,27,17,-51,2,-53,28,58,26,-18,1,-23,-42,-13,-4,11,0,-51,-26,15,13,8,-24,26,-6,33,-17,20,-20,55,4,-25,-35,-3,48,-15,-11,19,-12,-40,-28,-18,-25,15,35,3,7,2,10,17,16,-13,-5,-22,-20,17,-43,-16,0,16,-18,-6,-29,16,31,-12,-31,18,-40,10,-3,-44,-8,12,19,-26,-20,7,9,8,20,-32,11,0,27,20,-31,-5,28,29,8,-18,5,-5,0,-1,12,21,-12,-8,8,-20,8,18,20,-8,13,6,48,-47,13,24,24,3,38,25,-17,27,-31,18,-37,-14,-4,27,-24,-15,-33,11,-3,7,3,15,24,14,6,-8,24,14,28,-34,-11,-13,17,-5,-12,-14,-29,-15,24,48,-21,7,13,8,10,-2,-16,4,-33,14,9,-7,-27,-29,-17,-13,-25,-21,-9,1,-29,-4,18,4,-4,10,-5,-12,2,-10,16,-8,0,-7,-11,-7,30,-16,-19,6,2,-24,-17,6,-14,-12,0,-8,1,-16,24,22,-13,1,-4,-6,1,17,7,-10,13,-11,-32,2,-25,-13,7,1,-11,5,8,10,15,-5,-40,-11,-3,-16,-4,-32,-4,-19,18,-20,-9,-28,-1,-25,4,-16,-14,-8,-5,6,-2,-20,-22,16,2,-11,-18,-3,-11,-14,0,13,-7,2,-31,-22,6,7,-22,-7,-7,1,-7,1,4,16,14,-18,-14,-2,10,2,5,13,9,-2,3,-17,-11,-19,-8,-10,9,-23,-26,-13,-1,-17,-12,45,-36,3,1,-7,-42,17,10,6,12,-24,-11,18,2,3,-8,-38,-31,18,-1,-16,17,-24,-10,29,18,6,8,-26,-10,-10,-8,-3,-21,-20,5,-9,12,8,3,12,21,0,13,10,-49,-23,1,2,24,-33,-31,30,-3,-50,6,-14,43,-12,-28,10,25,13,-36,-39,-3,-16,27,-7,5,-7,-10,-7,-12,-23,-21,48,-33,14,4,-34,-28,-1,-41,-9,-39,-2,5,5,-41,19,-27,32,14,-25,-18,1,29,-21,-42,-23,28,19,-16,67,-22,17,-16,-14,-45,-33,20,-9,35,-27,46,2,-38,-19,27,-16,41,-17,-10,18,-22,26,29,39,9,-3,2,9,13,-6,-15,9,42,28,-22,19,6,-25,13,-13,-35,-23,-59,-23,14,4,19,10,-33,-42,3,10,3,20,15,-11,10,-10,-25,12,-27,42,23,-27,10,2,-38,-14,-33,-61,-6,-8,1,-19,26,19,2,-30,2,36,37,6,-30,27,20,-21,0,35,-29,-4,-31,12,-3,-37,5,-7,15,-4,-30,17,-35,-27,7,25,-39,-9,-8,13,32,34,-45,-10,-5,-26,13,17,-23,-4,-6,39,-22,-29,-26,-8,-26,25,-23,-12,49,-3,25,2,-16,-20,-11,-46,6,-39,-3,-9,-2,21,14,41,-6,27,6,22,-21,-19,-11,15,32,6,29,-61,-1,-16,-4,-35,20,22,43,33,7,-10,-31,5,18,-25,-28,2,27,-19,-28,12,-6,23,-4,-31,-51,8,-29,-38,27,-1,-12,-14,-3,-32,-16,57,12,-8,-3,36,-8,-44,-14,-1,-20,-24,-14,28,-16,12,-9,24,-49,-35,-44,-8,41,23,35,21,-13,5,33,-40,-52,-6,-18,-35,15,4,-47,12,27,8,-17,-12,39,-18,-20,-33,-19,41,19,-7,-12,22,11,25,-20,-21,5,-19,-39,-6,27,-15,-18,20,-10,-3,20,2,-17,-36,-17,-21,10,-2,-4,10,-34,15,-11,-13,10,-27,16,-7,-4,-20,10,-13,5,16,-37,-7,-32,-5,20,-3,-27,50,11,-13,11,-44,-1,50,30,-10,7,11,9,-16,12,-7,22,15,-36,-2,35,23,20,31,-10,2,-19,16,-14,50,-46,16,-17,2,15,-5,-30,-21,-26,-17,-14,-43,-21,6,7,20,-24,15,-1,-19,1,9,-2,39,13,-8,6,-43,-3,-16,18,-12,-33,-23,5,-9,3,-21,-25,11,-11,-1,-3,8,14,0,9,-28,-7,9,-3,-20,10,10,-3,3,12,6,-28,11,6,14,-4,-20,-5,11,6,-9,6,-9,6,-1,-11,-2,-17,15,15,-15,-19,-5,14,-13,-10,10,24,-10,-26,-40,-23,3,21,20,27,6,23,27,0,-10,1,22,-8,19,-45,-5,30,30,-30,19,10,-29,9,-1,26,12,16,-34,-40,-42,10,16,-8,-6,32,15,50,45,11,8,5,2,-30,-20,-26,2,-31,8,7,-6,-22,13,20,5,-25,-29,-2,47,-19,-7,-25,-43,23,-32,8,-23,-12,-23,28,-12,27,-8,-13,-5,7,-3,29,40,-6,-3,30,-15,-7,17,-21,8,-2,12,-30,-25,-12,-21,7,19,30,-5,-27,-36,8,3,-32,34,19,-3,-27,26,4,-44,-5,-57,34,43,17,35,29,-18,9,-26,16,33,5,-38,15,-26,-21,0,25,-1,-21,-22,6,-14,-10,-49,-29,33,20,-33,-20,-4,17,-22,0,-36,-13,26,-62,-6,-28,6,10,-7,-43,12,-2,45,8,-34,-23,-12,-32,22,-10,-6,29,26,16,7,-53,27,9,-1,-25,-9,16,-31,31,-8,-11,-44,37,-5,-25,14,9,-6,5,-13,5,40,10,-20,14,21,11,16,11,35,27,2,9,45,-17,-6,-11,-3,-3,-8,-5,-4,-13,-4,-44,-14,3,-26,-15,-55,-15,-15,0,33,10,34,-12,-12,-1,7,-29,12,42,19,-13,-3,11,-6,-6,-18,14,-2,-32,3,8,11,-6,-12,-18,-16,4,19,27,-15,-7,18,-35,3,23,34,-26,43,-54,0,-11,-19,-28,-8,-20,14,8,-5,-33,-1,-19,18,-31,-59,-34,31,5,11,-1,5,5,43,14,19,-17,21,-1,14,-55,18,-38,-54,-51,57,45,0,-25,13,13,-2,-23,-43,-22,49,32,-26,34,-23,-43,-24,-50,-10,14,25,-4,-44,11,36,-12,21,27,27,9,34,-21,-10,18,-16,-19,-15,-2,3,-10,13,30,32,38,14,-17,8,-22,-3,-1,-19,17,43,-20,-11,4,2,-22,9,50,16,-33,-7,-27,20,30,12,-26,3,-26,-47,12,0,-1,-8,-12,6,13,-8,-47,14,-4,26,5,-12,30,0,-39,-6,-31,21,-18,-25,-35,-4,-7,-11,-13,-48,37,10,-32,-35,-20,7,8,23,-49,1,20,-15,30,-13,18,36,-73,-21,-27,-2,-18,37,-27,15,16,18,3,44,-18,31,16,-20,9,-4,-6,27,-17,20,-14,-41,39,5,7,-6,3,-34,17,-14,-32,-4,-7,-21,25,-31,-20,4,-4,24,-15,26,16,2,-33,27,-34,-4,45,-2,-44,50,15,-24,-18,19,-5,0,-4,1,-49,27,32,30,1,20,31,-5,-35,-25,1,20,-34,14,-20,29,11,18,-11,-37,52,3,-62,-5,-23,-43,8,-46,-43,23,1,-26,-25,0,49,-5,12,-2,39,42,-4,9,-2,30,3,-27,6,-5,-14,39,-41,-8,5,-3,10,-36,18,7,-25,-9,-3,-34,-21,11,-10,-12,5,2,6,15,9,11,4,-24,-10,-20,-7,-24,26,-9,20,21,2,27,29,-11,13,-34,-8,23,6,-8,1,-43,1,28,-20,-13,16,-12,58,-14,4,-8,-5,-11,-4,15,-10,-13,-14,-6,34,-14,16,0,15,-12,10,8,11,49,30,21,-35,26,-1,-3,-8,20,1,10,-16,-5,10,-21,-16,-35,-21,17,12,35,-2,-7,9,-13,-13,-29,-10,-24,-13,14,6,14,-26,-3,-10,-5,-1,-38,-18,-10,30,-23,11,-2,-27,42,12,3,17,12,32,-4,19,-6,9,8,20,-30,10,-23,21,7,3,-34,-61,-50,-2,30,1,50,13,-13,-6,15,-1,27,29,-6,-3,2,-33,-77,-11,-19,-7,-10,-3,-8,43,28,-20,-36,-20,-38,-25,14,-39,44,-46,24,-14,8,0,-2,-37,14,-43,-32,-27,-1,24,-26,13,4,-24,-21,-24,15,27,3,24,16,-7,14,-14,3,6,-12,8,7,-44,-6,-8,-11,-9,8,11,42,-10,0,-9,21,-23,5,-2,19,16,-4,-33,-10,-11,21,11,6,10,27,3,2,-33,24,10,-17,6,15,39,15,4,-23,-9,3,0,16,9,40,-21,-17,15,46,67,34,-19,9,18,14,-18,-38,8,-11,-2,-13,-7,0,60,76,17,36,-13,-44,3,-52,5,34,9,0,9,-19,-33,-36,-43,13,-21,54,54,51,21,3,13,-8,35,-8,-21,8,-24,-13,-7,-12,10,-15,-6,9,-26,-2,-24,41,7,-8,-22,18,59,15} +#define CONV4_PW_BIAS {10, 3, -16, 27, 9, 15, 16, 33, -20, 75, 56, 18, -39, -16, -47, -34, 33, 45, 32, 31, 67, 55, -99, 12, 57, 40, 16, -55, 50, -33, 46, -4, -31, 50, -17, 11, 50, 21, -4, 12, -26, 23, 84, 11, 49, -4, 20, 33, 56, -4, 52, -13, 4, -3, 3, 33, -13, 64, 3, -15, -4, 17, -15, -42} +#define CONV5_DS_WT {-6,10,-9,27,21,30,36,46,-15,-25,27,23,-12,-12,-11,13,10,27,35,-19,30,17,-9,46,20,-33,-14,-13,22,-13,34,-15,-1,15,47,-11,-32,40,-14,-19,-15,117,5,22,23,25,26,10,23,-10,17,-15,-8,-105,-16,24,-3,-13,-14,48,-14,32,-11,-11,-8,-24,0,29,24,35,34,37,-8,-27,27,31,-15,-12,-14,15,14,26,33,-12,30,25,-9,40,19,30,-21,-12,21,-14,31,-11,5,34,41,-8,-10,41,-17,-16,-9,6,19,31,20,32,33,14,24,-10,30,-13,-9,26,-17,18,-24,-16,-21,49,-2,33,-19,-15,-6,12,0,24,16,34,34,22,-15,-17,37,14,-14,-13,-19,12,14,21,34,-12,25,17,-9,24,19,-39,-2,-8,23,-5,27,-21,-26,18,39,-6,-13,39,-16,-16,-17,-56,9,16,15,22,37,11,18,-8,9,-8,-8,29,-10,22,-2,-11,9,48,-14,27,-16,-11,-5,-3,-38,-1,2,-5,5,-6,-4,-1,7,4,0,-10,-8,1,3,-1,0,-23,0,-4,-6,-2,1,-21,-15,3,0,-2,3,-3,1,0,3,-2,-23,-4,0,7,1,-36,17,-6,0,0,-2,3,6,-1,10,-2,-13,-23,-5,1,3,-5,-2,6,-7,3,3,-4,-5,-20,-8,-5,3,-3,6,0,1,-2,2,-1,-1,-9,-2,-1,5,0,-4,-22,-1,-7,-2,6,4,17,-14,3,1,-2,1,-3,1,5,4,-3,-10,-3,-2,5,4,65,23,-4,-1,-1,0,3,4,-11,16,-8,-13,12,-5,1,-19,-6,-9,6,1,5,4,-1,-6,2,-31,-3,1,-6,3,-3,-2,2,3,-10,-2,-6,2,-2,2,-2,3,-20,3,-8,-4,2,-2,-13,-9,3,-1,-1,1,-11,-15,-1,5,-2,-10,-14,-5,7,0,-26,17,-8,-4,-2,-3,1,-3,-3,4,-2,-11,11,-1,0,0,-2,3,-1,-8,4,1,-3,-11,-2,1,27,14,28,43,35,-12,-17,25,37,-12,-9,-7,7,15,28,35,-12,24,14,-8,42,20,-36,-14,-13,28,-10,35,-8,7,2,42,-14,-17,42,-19,-15,-17,67,8,23,19,21,30,18,26,4,10,-15,-16,23,-12,28,9,-14,3,6,-14,30,-16,-11,-18,-29,-2,24,21,30,37,42,-5,-23,21,35,-12,-11,1,10,19,25,34,-6,24,24,-9,52,21,29,-22,-14,23,-15,37,-1,9,19,42,-11,-8,41,-20,-14,-4,71,17,37,26,31,31,21,31,-5,28,-20,-14,27,-20,21,-18,-18,-24,10,3,29,-2,-10,-6,2,0,21,17,22,32,37,-16,-20,31,55,-9,-10,-2,18,16,18,30,-11,21,22,-6,41,17,-45,-1,-10,22,-10,32,-7,-11,11,43,-11,-13,43,-20,-14,-13,-80,4,31,25,31,30,15,17,-16,30,-19,-11,22,-15,20,10,-9,16,-1,-13,29,-4,-11} +#define CONV5_DS_BIAS {28, 16, 34, -44, -46, -52, -54, -63, 51, 95, -79, -80, 43, 51, 40, -39, -58, -52, -62, 82, -56, -92, 27, -76, -52, 14, 60, 46, -61, 51, -57, 29, 15, -87, -63, 55, 75, -57, 65, 63, 36, -60, -115, -57, -52, -42, -51, -44, -97, 28, -103, 59, 73, -23, 63, -42, 16, 80, 12, -79, 17, -45, 30, 65} +#define CONV5_PW_WT {-10,50,-13,-9,0,8,26,9,-17,-6,5,-25,-16,27,-33,-33,-7,-31,-46,-27,-36,-39,-6,-2,43,-4,-8,-9,9,-11,9,-1,34,16,74,24,-46,56,-9,-18,32,-22,-19,27,-23,68,45,-1,1,18,5,38,9,11,3,-23,25,12,27,-3,45,-32,-12,-32,-39,5,3,13,20,27,37,-43,-49,37,21,15,3,29,54,21,-35,-27,-8,12,56,-3,-55,22,-27,-63,53,7,11,23,9,1,35,7,92,-7,-12,-40,-3,-27,37,-22,10,15,8,36,-30,-52,-24,54,10,33,31,-30,25,-29,59,48,20,31,30,-49,-94,-39,-78,-35,-5,-42,-72,11,-10,-29,4,34,-24,21,-37,-57,17,33,-41,74,70,60,-25,3,13,-40,-1,7,-6,42,-33,56,39,33,-28,8,-63,-59,-31,50,-19,-101,-23,3,-11,45,-14,-35,4,35,3,-40,7,9,30,25,42,-13,-37,49,-40,-5,18,57,-39,21,11,-49,10,-13,26,-18,8,-22,-15,4,-18,2,81,-17,16,-4,17,28,-2,24,14,17,37,55,56,-15,26,12,13,5,-6,11,-44,34,11,-87,3,-64,17,-85,4,-33,-48,-33,8,-11,-4,-22,4,-34,-8,32,47,-5,29,-6,-45,-60,13,-14,-19,-24,-9,49,39,-16,-34,21,-15,-3,-40,8,32,22,-6,-36,10,-18,-49,26,14,-11,-18,-7,29,37,8,45,0,39,24,30,-31,-16,-3,-34,32,27,-64,-38,-15,10,-31,-46,-10,13,-28,12,32,80,12,-18,6,3,32,-21,-38,-11,24,-55,-11,30,-29,63,-24,-39,-13,-55,-24,-10,-35,52,12,74,67,-36,-1,12,8,-19,-16,24,4,7,-36,33,-17,-6,-16,37,38,-21,6,-12,18,42,-35,-65,-26,-9,-13,21,10,-3,20,46,5,-53,-53,3,2,16,-24,-11,-7,-4,-3,31,5,-24,21,-7,12,-1,22,15,-22,-7,54,-7,-20,31,-16,-7,-21,-55,-2,1,-7,4,-39,21,-21,-21,-9,-13,13,-55,-41,26,-48,6,-19,-12,3,16,57,19,-32,-17,2,12,-8,-7,-5,13,-53,-8,-30,46,-11,-109,-15,-11,-27,7,36,56,17,9,3,7,-11,34,31,32,-16,24,-32,-15,-5,-24,-13,2,-31,10,-1,48,11,-17,-29,-22,56,-17,-42,-12,31,-23,-62,38,31,-12,-2,0,-12,-9,11,-18,-35,-19,-23,-4,20,-37,-9,29,-6,25,52,31,49,12,-19,27,-16,37,-6,18,4,37,-29,-28,9,32,1,22,-24,27,42,4,14,58,71,43,50,-18,22,35,0,-48,31,37,-20,-22,-2,-27,28,-5,-7,35,-3,-16,-42,27,-7,-23,-35,-20,-22,-22,-7,23,3,19,31,38,-5,-21,16,-1,-12,-26,34,-12,-19,48,-39,33,-20,-26,-11,13,8,-5,-30,31,113,31,38,50,-2,-12,-7,23,18,17,13,-6,53,-20,33,21,-21,10,29,7,30,-41,47,-16,59,-5,-24,5,-9,-7,39,0,-16,-32,-28,-15,-36,-6,7,-6,22,32,38,4,4,-36,46,-30,-28,25,1,-9,-6,2,-4,-6,11,-45,-10,-17,1,-18,11,25,9,-12,7,-5,3,37,25,6,5,37,-9,-41,59,-19,46,-15,-10,-2,-36,8,-5,38,-13,42,50,-29,33,-20,9,-37,-29,14,-65,6,0,31,-45,-29,-32,38,-27,-1,35,-20,15,34,-53,-11,10,-9,14,57,97,-5,16,-32,-34,17,-27,-13,26,35,-15,-5,13,15,28,-63,2,-5,27,-7,47,-24,20,-4,-20,-3,-3,-29,10,13,4,11,35,-29,4,7,115,-17,11,37,-9,-17,7,3,33,6,-44,4,-22,-16,19,16,-5,-27,-5,-7,-5,16,42,-37,-34,-12,17,38,32,12,22,-1,-14,-40,-25,13,7,8,-9,6,-10,-29,17,44,18,3,35,-24,-2,53,-9,3,65,-7,-27,3,-34,-13,48,-45,3,-41,-51,-33,-9,22,52,24,-48,12,-32,-52,9,27,18,-14,69,5,-34,36,6,-39,-3,33,-12,65,-6,-20,66,12,-42,73,-39,-42,37,8,-102,-21,-34,66,-4,4,4,-60,21,34,61,1,-2,22,-23,6,43,-13,-7,-11,-17,5,17,72,-49,30,33,42,-38,-1,-6,-38,-19,20,-22,-12,29,-47,-7,52,-24,-32,51,-27,-60,-61,22,-18,25,48,23,44,13,-60,5,4,-17,2,58,15,48,1,-30,-62,4,16,3,38,-6,-14,-3,45,50,8,1,-16,14,32,10,13,0,36,29,-8,45,2,36,-14,1,-22,-66,-14,3,-23,-41,-11,-15,4,-26,-12,-13,-10,-49,28,14,-6,-28,-5,23,46,-24,2,27,-29,-30,-12,0,-53,-13,49,60,16,24,1,-18,-2,-33,68,-21,-37,-35,35,-9,19,-40,-14,7,49,4,-1,-11,12,0,8,45,11,14,62,-13,12,-12,73,-7,-24,10,23,29,60,-4,-5,-8,35,23,-36,-3,-14,-12,39,-16,7,18,0,46,31,2,3,-38,-21,-22,-23,-12,-66,3,7,31,33,29,6,91,-8,1,13,15,71,7,21,-18,13,-27,30,-29,-53,-27,4,-15,-40,27,-24,-10,-25,36,23,-8,51,-20,-34,-35,-18,18,-6,49,-54,-9,-7,1,18,18,-31,-20,-1,12,9,-70,-57,14,0,-49,2,-34,17,-31,-20,46,13,-4,7,4,-53,15,0,-44,-7,104,-58,-1,-18,-71,-11,6,12,29,35,37,-34,-19,-3,34,-47,23,6,41,18,3,34,-15,-35,5,-17,11,12,24,-6,12,-50,39,13,27,70,-8,26,37,-32,-15,21,41,11,6,-45,-12,-78,-42,21,-19,35,46,-9,-1,43,-38,-6,23,-105,-5,-39,-42,19,-60,-9,22,24,-16,-32,-61,-26,-38,-21,33,-4,-49,24,8,-3,-36,1,30,35,17,72,-66,-40,-13,5,8,16,9,32,28,-11,17,-9,-2,-23,14,-6,63,3,-32,-30,-35,11,-58,47,4,13,6,-7,28,48,8,-7,-6,13,35,18,-40,-40,55,-55,11,46,-10,2,28,-31,-67,-12,-37,-15,15,-18,28,-6,-53,-30,14,-42,8,20,-13,-11,28,-8,-20,20,-25,76,16,-44,-44,0,-17,2,14,16,-8,-72,-22,22,46,-36,-3,17,-19,10,-46,29,54,32,56,34,65,-29,-34,-29,-9,2,42,-58,17,73,-2,-21,24,-11,-55,-38,34,-27,-14,45,11,30,-17,-51,-6,-21,-51,8,-7,-30,19,-12,-27,5,-4,27,-17,-5,12,16,-7,26,12,4,41,28,-27,-1,-8,-17,32,64,-14,-29,-15,6,9,28,-12,-10,3,13,30,11,-15,-11,15,-35,-31,-14,-30,-74,61,-21,-11,-21,-7,1,16,7,9,48,-14,-16,30,4,3,20,3,1,-37,-34,-23,-22,-34,12,40,3,9,30,-12,-8,25,-9,-32,6,28,-17,14,23,-33,48,-16,37,-6,-21,17,-66,62,-19,-1,24,-13,0,-8,2,-62,-28,31,2,-22,16,4,8,30,24,-44,-32,-30,53,36,-6,44,-44,13,-33,6,11,-23,-9,-23,15,-4,29,8,28,-16,-30,-23,12,33,26,-35,18,55,10,-15,-8,70,-14,-9,-36,72,-1,-30,39,-30,-10,-51,91,43,-60,-14,16,50,21,8,32,43,16,33,9,4,-14,25,-24,-35,7,-7,-67,-2,-26,15,-52,-17,-9,-84,-79,31,13,-25,-11,38,16,-42,5,20,26,-35,-34,-18,-16,-6,-17,12,21,-45,-16,-55,2,-38,56,-19,-25,10,-14,-27,-45,-1,-17,-12,-9,-50,22,-8,-16,-29,-38,-5,-1,9,22,67,47,54,36,4,-8,-22,56,3,-6,-1,26,-22,57,50,12,28,-16,-2,-73,-23,-31,51,-52,2,-17,-19,-27,-25,33,44,-14,-4,-50,22,-26,-35,-4,32,-44,-49,23,-7,44,-62,-33,56,-30,-51,-4,-35,0,17,31,-6,-27,-60,26,-14,15,-40,12,1,-29,-53,-33,-16,39,-41,-20,-2,-21,1,-11,-20,14,11,-24,42,43,8,18,37,50,-44,83,-19,-78,-24,10,-3,42,-31,-3,27,9,-2,39,4,-27,15,-6,63,-17,27,55,-18,-8,25,45,-33,5,29,23,-31,-9,-26,-49,-19,5,9,-1,0,-24,-62,13,0,-16,25,67,48,3,20,-38,-30,-8,51,51,-27,-13,-23,21,-7,6,32,-8,-77,-68,-9,42,4,-7,-37,20,3,-19,-41,37,41,32,1,-9,-8,-41,-57,51,-6,8,-27,24,10,-25,-29,21,43,-36,4,10,-5,-6,-48,7,-21,24,-8,-33,-10,-15,-15,14,-26,25,13,65,38,11,-7,-27,26,-35,14,-15,-15,-14,-53,-1,45,36,-15,-2,19,-76,-22,28,-18,-41,-6,20,-26,35,-26,-5,-26,-28,-20,-37,6,-5,44,27,9,-38,-21,35,-47,29,-9,0,30,-33,-42,0,21,-26,-11,-21,-23,-23,-36,-59,4,14,-12,28,15,1,11,-8,25,31,18,-11,-45,-18,-20,-20,27,-44,-6,44,32,-12,17,0,56,-62,1,-40,-15,48,3,16,-37,-12,-26,-48,-18,33,-9,-48,28,52,14,3,50,50,21,-6,2,-10,0,71,29,6,-11,59,5,16,-30,-40,32,36,-13,-28,43,4,-27,-8,0,-3,16,43,9,1,-1,-26,-8,-40,-27,20,-9,-27,25,-37,-26,5,41,-2,-1,-15,4,72,6,41,55,-6,8,15,-42,36,-9,24,-1,34,-37,5,21,21,0,17,40,21,43,-15,1,5,35,-45,-7,-39,-8,51,-15,10,-18,-3,-26,11,-26,33,17,13,9,14,-22,19,77,76,-23,0,17,-43,-7,-9,-9,36,-13,4,41,22,-45,20,-2,-49,-14,25,-8,-19,-2,-31,-29,4,-33,-53,7,-6,6,-33,-23,-22,20,2,26,-4,-39,-16,-26,-16,-12,52,-30,40,53,-4,-17,-24,-33,22,-14,69,9,-52,15,11,45,-31,-35,-21,13,58,8,22,6,-29,25,-22,50,31,-37,-11,-5,-31,-34,-7,-20,10,-35,-90,18,-14,3,-34,10,-6,-43,-13,7,30,-34,-17,-20,-51,-6,8,39,40,-66,29,-47,-46,-9,-24,-7,-8,40,11,4,34,25,-35,-7,-44,43,-34,-18,47,20,8,-51,-5,30,-2,-35,28,-2,-9,47,-29,26,28,-20,33,31,-33,-1,38,-40,-3,47,26,-49,4,-19,0,-14,-32,-18,22,9,27,-8,4,31,33,7,23,13,6,15,21,29,39,17,34,58,-26,23,46,-14,-25,32,32,2,28,34,-31,3,42,-29,-1,5,-25,14,35,-10,-7,0,-7,-10,-30,-8,-27,-3,16,27,20,-24,-70,60,0,-7,-40,9,-29,-25,-1,-10,29,13,34,52,-28,15,-11,-25,88,29,-24,8,48,-3,5,-5,-3,-10,-30,-34,-15,36,-8,-18,-30,-36,-30,-62,-68,-41,-15,-3,16,-35,-17,-49,-6,-56,34,21,20,-25,-3,-32,-50,32,41,-18,-8,-21,-34,11,20,-21,17,7,-9,43,27,-39,53,-27,-1,5,18,-26,-17,-98,0,-4,-6,-10,-63,-17,13,23,-11,-19,35,49,24,36,70,-45,-30,-12,-12,26,86,-44,77,-4,-28,-19,-65,1,18,50,11,2,-41,3,8,55,19,-40,2,-24,44,-3,37,11,-1,3,-17,11,-30,30,-50,13,21,-36,26,-24,-1,31,-49,14,-47,13,-89,34,0,-7,3,18,-10,-65,-15,-11,-25,1,38,75,7,-6,41,-4,-71,13,-28,13,-14,-42,37,67,1,-46,92,16,-31,-19,26,30,-9,-32,-39,-7,-1,-64,-13,90,-15,-23,-32,4,12,-8,31,6,33,21,8,31,-48,23,-15,22,17,-51,-6,10,-17,-22,42,-66,-20,19,-43,-16,65,38,-11,41,12,5,-68,-31,-37,38,-36,-36,11,10,48,-10,-65,-39,-25,22,-25,35,22,10,44,-25,89,-25,-43,-18,22,70,-10,11,-35,10,-20,-1,16,-27,-29,76,-14,7,23,-70,-47,22,-70,6,-33,-47,-10,-59,-67,11,19,-14,-14,-3,-4,-35,-22,0,27,-25,-2,0,-36,-16,15,34,30,-43,33,-74,-66,-25,-10,-6,-6,-12,39,29,-14,26,-17,-13,-50,-23,22,-22,-24,-30,27,35,13,-73,13,36,37,63,60,-25,-25,4,-42,-1,-9,-28,-73,13,-5,60,24,-9,43,94,-39,15,-13,1,34,-12,34,13,-7,-45,-64,-22,-20,-8,-64,11,11,23,-29,59,2,-14,-42,12,-10,-28,43,36,49,-20,29,-14,-8,-18,-60,-18,-3,-43,14,5,-22,-44,18,-36,-28,7,11,-25,9,6,-35,28,17,12,53,-25,-18,1,67,8,-30,49,-8,-34,29,-53,14,-2,14,8,25,-21,-20,-23,15,101,53,28,-25,22,1,-21,36,20,30,25,1,42,-33,41,57,8,-10,-9,31,-4,-37,-26,9,6,61,-5,-32,8,7,19,-11,-25,-47,6,-18,-33,-34,-23,-37,27,-29,-14,21,-4,-68,25,-20,-17,8,-29,-1,-66,-16,-14,67,-6,-55,38,44,-20,24,25,41,-40,9,4,-21,5,31,52,41,-11,77,-16,20,19,1,-1,0,-10,-26,-56,-50,0,-8,-29,3,-63,-7,-46,35,-32,29,-14,-3,40,24,11,-14,9,55,12,-15,-11,34,-24,-19,-7,-24,-7,73,91,-32,-13,2,-40,-1,-31,-3,-21,-40,-13,-5,-16,18,-10,-30,13,3,-4,-1,52,26,-11,8,69,-23,-14,51,-18,44,-9,42,-22,-11,12,3,22,76,18,32,23,-8,-25,9,-1,10,10,-10,-17,-1,-31,17,22,-4,-18,-13,4,-10,38,4,-1,3,-7,-37,-13,3,-14,6,-3,-5,-12,26,16,-10,16,-35,-23,7,-36,25,30,-25,-4,-7,-40,-38,18,-5,-1,-23,-21,-8,-15,-14,16,-10,-9,19,-81,-53,27,-41,28,0,-32,-20,-19,-14,-29,35,30,22,8,-11,3,-34,5,52,0,20,26,11,-20,-11,-12,-59,27,50,41,-29,-12,19,17,6,-4,-37,8,-42,-29,-4,-34,-26,6,-53,-27,30,18,-26,27,61,31,-2,64,66,-34,-43,8,-2,-34,55,-31,58,24,2,-25,32,43,2,22,-45,-14,14,33,1,-7,36,35,23,8,1,-23,-20,102,7,-1,54,-38,-19,54,1,3,-20,-45,28,30,-3,16,4,16,-63,20,-7,12,-21,-2,-26,-7,-5,8,-6,7,35,-21,25,-3,-7,23,2,47,-15,34,1,14,-4,-3,-26,-30,-7,-16,-55,-21,25,-43,45,-1,-50,-11,-44,8,10,-77,-26,40,-1,-44,-26,-15,5,-23,16,23,5,15,-6,-11,16,15,2,-11,11,28,-59,-18,-12,-26,-99,4,6,-17,29,46,23,-16,-17,-26,-61,14,7,38,15,-33,-3,-28,23,-21,53,17,-16,31,16,-23,35,18,-25,-19,-22,-22,27,13,-61,43,-14,-21,7,-25,-34,37,21,-42,-12,31,-12,-38,-11,-15,17,3,-31,-16,22,-25,6,25,-23,28,-53,-4,-15,-4,19,8,18,-29,5,17,-9,-23,25,-9,-18,11,28,39,44,-35,77,22,9,9,-3,11,4,1,-33,7,-32,-18,4,49,34,17,-31,-6,63,-17,33,-27,38,49,1,-56,-22,9,16,8,22,-28,5,-49,-18,28,9,20,5,30,-34,8,10,-26,11,-24,56,-16,-83,-46,-19,7,0,-9,-12,-11,-2,-3,54,-17,-15,9,-12,39,-4,14,35,4,10,14,28,-32,16,-28,-34,-9,-28,-14,-15,-50,-30,-8,-25,-6,-4,-7,18,10,-2,17,-7,13,34,30,9,-19,0,-22,7,3,-15,-9,58,33,5,14,-7,-45,-27,-10,-17,12,-18,-80,21,-33,6,1,-70,-10,47,3,-38,15,15,10,19,35,55,1,4,-7,-7,-12,82,22,0,32,2,18,62,12,-50,6,17,54,0,21,-37,-16,-24,-60,2,50,10,8,-23,37,12,-8,11,18,31,20,0,7,15,-26,-31,28,73,-15,15,42,-23,-69,102,-43,53,55,-35,-13,11,13,-2,45,41,17,-43,-50,-18,-10,-2,-6,12,62,25,-44,9,-26,-12,-17,-25,-16,70,24,26,-26,3,-40,0,-2,-22,42,-24,3,-13,9,10,-1,1,-3,4,47,28,44,9,-1,31,-4,-46,-10,0,-29,6,-40,-53,-6,-11,1,-8,2,-14,-26,-30,-12,31,4,-9,-4,-16,-35,-5,39,15,15,-2,-27,-38,-30,-1,25,-20,4,43,0,23,-16,69,8,43,-2,-20,6,-45,55,-16,-29,69,9,5,13,-9,-47,-32,57,-12,-28,8,-58,-14,48,15,-30,-10,-27,-6,48,-17,34,-42,13,-34,4,56,-28,-24,-6,43,-10,10,-5,-10,-13,20,-8,-21,16,5,-3,7,93,32,1,13,77,-8,9,-68,26,-4,24,-21,-8,21,57,-40,-18,46,18,1,-37,1,26,49,-58,37,-2,22,19,-25,46,4,13,-15,38,1,-25,1,-12,34,9,22,-17,-9,-23,19,-7,-76,21,-9,19,45,34,2,-45,-2,-11,24,-10,36,38,6,4,-26,13,28,8,1,25,-44,-72,-49,-23,-25,26,-49,2,7,-7,-14,-8,23,-26,-12,9,-6,11,-46,-9,25,-33,20,-7,5,12,61,77,15,-9,-18,2,26,3,12,-26,8,-9,-44,-22,-45,11,-92,-26,-20,-20,-5,26,4,44,4,11,-37,-3,22,7,17,14,3,-34,-37,12,-30,8,2,-24,25,20,-33,9,-20,17,-6,5,12,41,-10,-18,9,19,16,-14,9,24,-37,-5,16,44,22,9,41,-9,-16,35,-35,33,1,20,-22,-25,-16,-19,-11,12,-72,-1,-60,16,-5,17,-13,69,5,-41,-36,-4,-41,-19,32,51,-3,7,11,-41,-34,21,22,0,-51,-6,-9,7,-44,-5,46,32,34,-39,-10,-52,42,-39,3,15,20,39,-17,-16,-50,9,30,-15,-16,-3,28,14,-2,-8,-30,2,11,42,-41,-10,19,-19,10,-41,27,-10,-49,-17,-16,-38,-27,-35,23,57,-6,10,-2,-5,-40,-21,0,26,-24,-17,-4,-24,12,12,16,-36,39,-18,-62,-21,21,45,-1,4,-8,12,27,-29,23,41,23,30,11,24,-19,37,34,36,7,-4,39,-5,-3,21,-42,55,6,22,-15,-39,42,14,-28,9,-54,21,18,-22,-31,-26,-48,-20,-28,-21,-33,9,19,-3,33,18,-24,30,12,-38,-60,38,3,-30,-4,-58,65,13,12,25,53,-17,53,7,-22,41,-16,48,-33,-23,-27,-43,24,-6,65,2,-9,22,35,24,-19,6,10,0,70,-47,-28,-40,-30,5,6,-18,-56,39,-21,-10,-15,-15,-2,16,0,-11,-6,3,22,13,-59,-11,-40,23,16,0,-19,10,20,-36,-5,50,-4,-22,-28,52,26,-28,-2,-38,-23,-14,-24,10,-6,36,-33,-56,-9,-47,27,16,86,-11,-28,50,-1,-25,22,60,67,35,53,-62,43,-34,40,48,-28,-46,-77,-11,-29,-5,-47,-20,31,4,-15,-18,35,48,40,-8,-5,9,-15,-38,39,-55,-3,-10,21,9,-19,27,-19,68,-35,-21,4,40,-31,7,-34,45,-73,19,27,39,11,-32,-17,24,20,-11,58,13,7,83,-15,14,31,-12,11,65,29,-25,67,-42,-4,50,-9,-48,-49,-13,-37,13,-37,-28,23,2,14,7,3,-32,44,8,9,24,12,14,17,10,7,18,50,33,-8,34,-11,-19,-63,9,-22,-3,4,-24,-78,-27,3,-29,30,-36,-8,-12,22,-22,-18,14,28,63,70,-15,6,81,16,13,6,-15,-49,11,37,33,-15,-9,11,-22,-12,-30,-14,7,-35,17,10,-21,-34,-29,-24,74,35,5,-38,-1,23,-34,21,37,9,-49,-53,15,-31,-21,59,17,25,-39,-25,-45,-77,-49,5,-35,4,-4,-26,-30,-9,-6,-32,-80,21,13,67,34,70,-24,-30,-7,-40,23,-22,-35,38,-47,51,55,43,0,2,9,-49,-25,17,-2,-115,-25,-11,-4,17,-6,-36,-14,19,-2,-67,37,26,25,22,27,-42,-16,23,-55,26,2,16,-17,-1,-10,-11,24,62,2,45,36,18,-9,-43,15,9,16,6,11,26,-14,12,38,14,27,-17,12,-17,-4,-52,50,33,-37,-15,-9,19,-12,20,92,-93,20,-37,14,28,22,-20,-48,8,-22,4,-31,-56,-26,6,-28,12,28,-13,-6,-25,16,-27,-12,-10,1,-32,-42,-2,25,27,24,14,21,8,45,-32,12,30,4,-8,-36,24,22,24,-38,1,-3,-18,31,-20,-25,9,-19,-8,19,-39,4,-10,-12,50,34,-7,-23,-32,-13,45,3,-36,21,15,28,27,10,56,-29,-30,-15,21,20,-24,11,4,25,-30,15,60,19,30,22,-38,-58,-58,-38,-6,-37,47,18,-27,-35,-41,-35,0,6,-2,3,30,25,11,17,-19,-27,-9,57,-18,-30,49,4,10,0,-17,-7,9,-5,-26,25,8,-43,2,-11,-29,38,14,-48,17,-17,-42,-32,-4,57,49,2,18,4,3,-19,21,29,11,11,6,0,-12,51,28,48,-9} +#define CONV5_PW_BIAS {23, -2, 56, 45, 45, 19, 87, -22, -5, 31, 8, 7, 22, 3, 43, 7, 75, 60, 39, 14, 41, 25, 73, 50, 40, 60, 92, 29, -6, 35, 87, -14, 22, 41, 59, 22, 99, 23, -2, 68, 28, 45, 21, -22, 98, 50, 17, 37, -46, 38, 2, 21, 67, 30, 52, -5, 36, 35, -5, 25, 97, 42, 22, 8} +#define FINAL_FC_WT {-24, -45, -33, -12, 33, 32, -64, -17, 1, -14, 36, 32, 46, -22, -34, -38, 35, 22, 43, -43, -54, -43, -37, -55, -35, -54, -62, -56, -47, -47, -49, -25, -47, 10, -44, 29, -50, -2, -36, -55, -46, -42, -18, -24, -4, -51, -23, -42, 40, -62, -40, -54, -43, -12, -52, -3, 29, -13, -14, -52, -40, -61, -16, -39, -40, -38, 51, -1, -39, -37, -1, 10, 2, -24, -29, -18, 32, -30, 52, -28, -3, -1, -5, 10, -11, -40, -25, 8, 32, 17, 11, 41, -29, 35, -27, 7, -42, 48, -11, -34, -10, 37, 25, -24, 41, -25, 54, -22, -9, -9, 19, 46, -17, -15, -35, -29, 1, -16, 18, 5, -27, -19, -2, 45, 35, -50, -51, 10, 8, 36, 44, -62, 59, -27, 6, -32, -55, -58, -43, -32, 4, -43, 32, 23, -39, -19, 40, 11, 12, -39, 57, 31, 15, 1, 48, -41, 6, -35, -28, -19, 10, -47, -58, 12, -18, -45, -41, 21, 55, -34, -39, -48, 42, -19, 30, -19, -10, -47, -8, 43, -60, 24, -2, -53, -17, 0, 12, -60, 54, -34, 56, -47, 55, 7, 13, -41, -11, 24, 36, 41, 51, 37, -6, 41, -19, -8, 21, -21, -10, -13, -35, -60, 43, -22, -54, -51, 54, 24, -9, -48, 55, -17, -17, 36, 38, -19, -10, -34, -15, -40, 25, 35, -24, 29, -49, -27, -40, -19, 28, -55, -14, -39, -20, 29, -11, -58, 2, -57, -20, -6, 9, 3, -35, -35, 37, -24, -30, -33, -10, 3, -33, -14, -55, -48, -28, -36, -15, -16, -6, -33, -40, 52, -27, -33, -5, 54, 49, -24, 49, 22, -45, 35, 17, 0, 43, 40, 27, -62, 38, -26, 0, 33, 25, 49, -12, -37, -49, 38, -45, -12, -33, -27, -46, -52, 18, 19, -22, -65, -44, -5, -3, 33, 12, -2, -60, 31, -25, 46, -27, -12, -46, 56, -3, 36, -10, -6, 2, 4, -16, 43, -16, 39, -17, -29, -39, -48, -43, -14, 17, 16, 11, -30, -45, -18, -28, -57, -52, 1, -48, -20, -34, 30, -6, -1, 48, -42, -46, -19, -44, -26, 0, -23, 33, 64, -39, -34, 44, -4, -13, -25, -9, 52, 2, 56, -23, 53, -32, -24, 59, -14, -31, 8, 32, -4, 51, 44, -33, -47, -27, -25, -44, 44, -36, -39, 22, -2, -35, 45, 21, 56, 43, -54, 4, -27, 23, 38, -10, 4, 29, -55, 41, 43, 32, -26, -14, -39, -11, -33, -12, -18, -32, 39, -12, 5, 7, -28, 1, -27, 49, 43, -44, -12, -17, -58, 42, -10, -49, -9, -47, -48, -13, -31, -40, -51, 24, 24, -9, -40, -34, -32, -6, -53, -13, -33, -52, 47, 5, -39, -11, -15, -14, 47, 19, -32, -31, -19, -23, 41, -57, 49, -18, -7, -44, 51, -12, 41, 35, -52, -5, 33, -41, -27, -31, 3, -50, -51, 50, -5, -2, -51, -4, 46, -20, 54, -45, 47, 15, -23, 54, -43, -46, -32, -54, -48, 25, 67, 53, 5, -37, -46, -34, 48, -32, 1, -7, -5, -27, 48, -44, -20, -22, -39, 15, -29, -18, -59, 1, -6, -42, 55, -13, -33, -54, 40, -14, -33, 41, -49, -20, 12, -57, 45, -36, -41, -32, 44, -26, 11, 25, -42, -23, -51, 13, 45, 26, 34, -38, -30, 51, 23, -12, 45, 53, -37, -35, -19, 54, 26, 31, -47, -24, -27, -50, 21, -21, 36, -10, -40, 43, 27, -25, 48, 11, -43, -44, -27, 33, -30, -21, -49, -51, -21, 14, -5, -3, -36, -28, 34, -8, 10, -3, 13, 43, -24, -31, 26, 42, -51, -42, -9, 21, -23, 12, -5, -48, -46, -41, 44, -59, -31, 28, -11, -44, -26, -31, 35, 2, 9, 18, -38, -10, -42, 51, 55, -11, -18, 49, 41, -35, -21, -17, -51, -57, 29, -20, -44, 32, -26, -29, 38, -18, 5, -10, 22, -57, -43, 38, 59, 0, 12, 44, 2, 24, -34, -63, -30, -17, -3, -14, -33, 58, -32, 11, 20, 49, -9, 56, 2, -27, 57, -51, -33, 38, -35, 43, 34, -50, -10, -21, 11, -50, -26, 15, 54, -47, 19, -34, -30, -46, -22, -13, -28, -54, -42, 25, 1, -47, 38, 20, -40, 31, -36, 38, 34, -3, -15, -23, 55, -46, -31, -16, -46, -28, -40, -43, -10, -47, 44, 6, 31, -35, -47, -52, -39, -18, 5, 45, -51, -25, 38, -10, -39, 36, -37, 8, 19, -16, 19, 6, -51, -11, -37, 4, 22, -24, -22, 44, 4, 45, 17, -27, 33, -1, 39, -32, -33, -8, 25} +#define FINAL_FC_BIAS {68, 18, -33, -10, 7, -2, -3, -9, 1, -23, 2, -1} diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/nn.cpp b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/nn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99bdaeca69d4f3c2bb37d0f2793aa04a85f57efa --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/nn.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 "nn.h" + +NN::~NN() { +} + +int NN::get_frame_len() { + return frame_len; +} + +int NN::get_frame_shift() { + return frame_shift; +} + +int NN::get_num_mfcc_features() { + return num_mfcc_features; +} + +int NN::get_num_frames() { + return num_frames; +} + +int NN::get_num_out_classes() { + return num_out_classes; +} + +int NN::get_in_dec_bits() { + return in_dec_bits; +} + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/nn.h b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/nn.h new file mode 100644 index 0000000000000000000000000000000000000000..678ab45a6e9d0531b3e050f2d15423dc1d18faeb --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/NN/nn.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * 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 __NN_H__ +#define __NN_H__ + +#include "arm_nnfunctions.h" + +class NN { + + public: + virtual ~NN(); + virtual void run_nn(q7_t* in_data, q7_t* out_data)=0; + int get_num_mfcc_features(); + int get_num_frames(); + int get_frame_len(); + int get_frame_shift(); + int get_num_out_classes(); + int get_in_dec_bits(); + + protected: + int frame_len; + int frame_shift; + int num_mfcc_features; + int num_frames; + int num_out_classes; + int in_dec_bits; + +}; + +#endif diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/local_NN/arm_avepool_q7_HWC_nonsquare.c b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/local_NN/arm_avepool_q7_HWC_nonsquare.c new file mode 100644 index 0000000000000000000000000000000000000000..a428837551f243fcf4ce9e8ec1743e7be795a570 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/Deployment/Source/local_NN/arm_avepool_q7_HWC_nonsquare.c @@ -0,0 +1,45 @@ +#include "arm_math.h" +#include "arm_nnfunctions.h" + + +void arm_avepool_q7_HWC_nonsquare ( + const q7_t * Im_in, // input image + const uint16_t dim_im_in_x, // input image dimension + const uint16_t dim_im_in_y, // input image dimension + const uint16_t ch_im_in, // number of input image channels + const uint16_t dim_kernel_x, // window kernel size + const uint16_t dim_kernel_y, // window kernel size + const uint16_t padding_x, // padding sizes + const uint16_t padding_y, // padding sizes + const uint16_t stride_x, // stride + const uint16_t stride_y, // stride + const uint16_t dim_im_out_x, // output image dimension + const uint16_t dim_im_out_y, // output image dimension + q7_t * bufferA, // a buffer for local storage + q7_t * Im_out, // output feature + const uint16_t out_lshift) // output left shift (scaling) +{ + int16_t i_ch_in, i_x, i_y; + int16_t k_x, k_y; + + for(i_ch_in=0;i_ch_in= 0 && k_x >= 0 && k_y基本信息 + +**发布者(Publisher):Huawei** + +**应用领域(Application Domain):Natural Language Processing** + +**版本(Version):1.1** + +**修改时间(Modified) :2021.12.29** + +**大小(Size):808K** + +**框架(Framework):TensorFlow_1.15.0** + +**模型格式(Model Format):ckpt** + +**精度(Precision):Mixed** + +**处理器(Processor):昇腾910** + +**应用级别(Categories):Official** + +**描述(Description):基于TensorFlow框架的DS-CNN网络训练代码** + +

概述

+- DS-CNN是基于卷积神经网络的音频解析网络。 + +- 参考论文: + + https://arxiv.org/pdf/1711.07128.pdf + +- 参考实现: + + https://github.com/ARM-software/ML-KWS-for-MCU + +- 适配昇腾 AI 处理器的实现: + + https://gitee.com/ascend/ModelZoo-TensorFlow/tree/master/TensorFlow/built-in/nlp/DS-CNN_ID1769_for_TensorFlow + + +- 通过Git获取对应commit_id的代码方法如下: + + ``` + git clone {repository_url} # 克隆仓库的代码 + cd {repository_name} # 切换到模型的代码仓目录 + git checkout {branch} # 切换到对应分支 + git reset --hard {commit_id} # 代码设置到对应的commit_id + cd {code_path} # 切换到模型代码所在路径,若仓库下只有该模型,则无需切换 + ``` + +## 默认配置 +- 网络结构 + - DNN with 3 fully-connected layers with 128 neurons in each layer + +- 训练数据集预处理: + - 模型使用 speech+commands 数据集,请用户自行下载。 + +- 测试数据集预处理: + - 模型使用 speech+commands 数据集,请用户自行下载。 + +- 训练超参(单卡): + - model_architecture: ds_cnn + - learning_rate: 0.0005,0.0001,0.00002 + - 单卡batchsize:100 + - Steps:30000 + - window_stride_ms: 20 + - window_size_ms: 40 + - model_size_info: 5 64 10 4 2 2 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 + + +## 支持特性 + +| 特性列表 | 是否支持 | +| ---------- | -------- | +| 分布式训练 | 否 | +| 混合精度 | 是 | +| 数据并行 | 否 | + + +## 混合精度训练 + +昇腾910 AI处理器提供自动混合精度功能,可以针对全网中float32数据类型的算子,按照内置的优化策略,自动将部分float32的算子降低精度到float16,从而在精度损失很小的情况下提升系统性能并减少内存使用。 + +## 开启混合精度 +相关代码示例。 + +``` +custom_op.name = "NpuOptimizer" +custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("allow_mix_precision") +``` + +

训练环境准备

+ +1. 硬件环境准备请参见各硬件产品文档"[驱动和固件安装升级指南]( https://support.huawei.com/enterprise/zh/category/ai-computing-platform-pid-1557196528909)"。需要在硬件设备上安装与CANN版本配套的固件与驱动。 +2. 宿主机上需要安装Docker并登录[Ascend Hub中心](https://ascendhub.huawei.com/#/detail?name=ascend-tensorflow-arm)获取镜像。 + + 当前模型支持的镜像列表如[表1](#zh-cn_topic_0000001074498056_table1519011227314)所示。 + + **表 1** 镜像列表 + + + + + + + + + + + + +

镜像名称

+

镜像版本

+

配套CANN版本

+
+

21.0.2

+

5.0.2

+
+ + +

快速上手

+ +## 数据集准备 +1. 模型使用 speech+commands 数据集,请用户自行下载。 +2. 获取数据集后,放入模型目录下,在训练脚本中指定数据集路径,可正常使用。数据集文件结构示例如下: +``` + # 最终数据集文件结构示例: + ├── DS-CNN_dataset + │   ├── speech_commands_v0.02.tar.gz + 则 data_path=./DS-CNN_dataset 即可 +``` + +## 模型训练 +- 单击“立即下载”,并选择合适的下载方式下载源码包 +- 开始训练 + + 1. 启动训练之前,首先要配置程序运行相关环境变量。 + + 环境变量配置信息参见: + + [Ascend 910训练平台环境变量设置](https://gitee.com/ascend/ModelZoo-TensorFlow/wikis/01.%E8%AE%AD%E7%BB%83%E8%84%9A%E6%9C%AC%E8%BF%81%E7%A7%BB%E6%A1%88%E4%BE%8B/Ascend%20910%E8%AE%AD%E7%BB%83%E5%B9%B3%E5%8F%B0%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E8%AE%BE%E7%BD%AE) + + + 2. 单卡训练 + + 2.1 设置单卡训练参数(脚本位于./DS-CNN_ID1769_for_TensorFlow/test/train_full_1p.sh),示例如下。 + +``` + # 训练batch_size + batch_size=100 + # 训练steps + train_steps=30000 + # 数据集文件 + data_path=./DS-CNN_dataset +``` + 2.2 单卡训练指令(脚本位于./DS-CNN_ID1769_for_TensorFlow/test/train_full_1p.sh),示例如下。 +``` + bash train_full_1p.sh --data_path=./DS-CNN_dataset +``` + +

迁移学习指导

+ +- 数据集准备。 + + 1. 获取数据。 + 请参见“快速上手”中的数据集准备。 + + +- 模型训练。 + + 请参考“快速上手”章节。 + + +

高级参考

+ +## 脚本和示例代码 + + . + ├── LICENSE + ├── README.md + ├── modelzoo_level.txt + ├── requirements.txt + ├── test + │   ├── env.sh + │   ├── train_full_1p.sh // 执行训练脚本 + │   └── train_performance_1p.sh // 执行训练脚本 + ├── model.py // 创建模型脚本 + ├── test.py // 推理入口脚本 + ├── label_wav.py // 音频标签处理脚本 + + +## 脚本参数 + +``` + --model_architecture + --model_size_info + --dct_coefficient_count + --window_size_ms + --window_stride_ms + --learning_rate + --how_many_training_steps + --summaries_dir + --data_dir + --batch_size + --train_dir +``` + +## 训练过程 + +1. 通过“模型训练”中的训练指令启动单卡训练。 +2. 将训练脚本(train_full_1p.sh)中的data_path设置为训练数据集的路径。具体的流程参见“模型训练”的示例。 +3. 模型存储路径为“curpath/output/$ASCEND_DEVICE_ID”,包括训练的log以及checkpoints文件。 +4. 以单卡训练为例,loss信息在文件curpath/output/{ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log中。 diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/fold_batchnorm.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/fold_batchnorm.py new file mode 100644 index 0000000000000000000000000000000000000000..6022efee4cebc9b46ea7bb17e8cf2c3a2b5e7ede --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/fold_batchnorm.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017-2018 Arm Inc. All Rights Reserved. +# Adapted from freeze.py to fold the batch norm parameters into preceding layer +# weights and biases +# + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import argparse +import sys +import numpy as np +import tensorflow as tf +import models +import input_data + +FLAGS = None + +def fold_batch_norm(wanted_words, sample_rate, clip_duration_ms, + window_size_ms, window_stride_ms, + dct_coefficient_count, model_architecture, model_size_info): + """Creates an audio model with the nodes needed for inference. + + Uses the supplied arguments to create a model, and inserts the input and + output nodes that are needed to use the graph for inference. + + Args: + wanted_words: Comma-separated list of the words we're trying to recognize. + sample_rate: How many samples per second are in the input audio files. + clip_duration_ms: How many samples to analyze for the audio pattern. + window_size_ms: Time slice duration to estimate frequencies from. + window_stride_ms: How far apart time slices should be. + dct_coefficient_count: Number of frequency bands to analyze. + model_architecture: Name of the kind of model to generate. + """ + + tf.logging.set_verbosity(tf.logging.INFO) + sess = tf.InteractiveSession(config=npu_config_proto()) + words_list = input_data.prepare_words_list(wanted_words.split(',')) + model_settings = models.prepare_model_settings( + len(words_list), sample_rate, clip_duration_ms, window_size_ms, + window_stride_ms, dct_coefficient_count) + + + fingerprint_input = tf.placeholder( + tf.float32, [None, model_settings['fingerprint_size']], name='fingerprint_input') + + logits = models.create_model( + fingerprint_input, + model_settings, + FLAGS.model_architecture, + FLAGS.model_size_info, + is_training=False) + + ground_truth_input = tf.placeholder( + tf.float32, [None, model_settings['label_count']], name='groundtruth_input') + + predicted_indices = tf.argmax(logits, 1) + expected_indices = tf.argmax(ground_truth_input, 1) + correct_prediction = tf.equal(predicted_indices, expected_indices) + confusion_matrix = tf.confusion_matrix(expected_indices, predicted_indices) + evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) + + models.load_variables_from_checkpoint(sess, FLAGS.checkpoint) + saver = tf.train.Saver(tf.global_variables()) + + tf.logging.info('Folding batch normalization layer parameters to preceding layer weights/biases') + #epsilon added to variance to avoid division by zero + epsilon = 1e-3 #default epsilon for tf.slim.batch_norm + #get batch_norm mean + mean_variables = [v for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) if 'moving_mean' in v.name] + for mean_var in mean_variables: + mean_name = mean_var.name + mean_values = sess.run(mean_var) + variance_name = mean_name.replace('moving_mean','moving_variance') + variance_var = [v for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) if v.name == variance_name][0] + variance_values = sess.run(variance_var) + beta_name = mean_name.replace('moving_mean','beta') + beta_var = [v for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) if v.name == beta_name][0] + beta_values = sess.run(beta_var) + bias_name = mean_name.replace('batch_norm/moving_mean','biases') + bias_var = [v for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) if v.name == bias_name][0] + bias_values = sess.run(bias_var) + wt_name = mean_name.replace('batch_norm/moving_mean:0','') + wt_var = [v for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) if (wt_name in v.name and 'weights' in v.name)][0] + wt_values = sess.run(wt_var) + wt_name = wt_var.name + + #Update weights + tf.logging.info('Updating '+wt_name) + for l in range(wt_values.shape[3]): + for k in range(wt_values.shape[2]): + for j in range(wt_values.shape[1]): + for i in range(wt_values.shape[0]): + if "depthwise" in wt_name: #depthwise batchnorm params are ordered differently + wt_values[i][j][k][l] *= 1.0/np.sqrt(variance_values[k]+epsilon) #gamma (scale factor) is 1.0 + else: + wt_values[i][j][k][l] *= 1.0/np.sqrt(variance_values[l]+epsilon) #gamma (scale factor) is 1.0 + wt_values = sess.run(tf.assign(wt_var,wt_values)) + #Update biases + tf.logging.info('Updating '+bias_name) + if "depthwise" in wt_name: + depth_dim = wt_values.shape[2] + else: + depth_dim = wt_values.shape[3] + for l in range(depth_dim): + bias_values[l] = (1.0*(bias_values[l]-mean_values[l])/np.sqrt(variance_values[l]+epsilon)) + beta_values[l] + bias_values = sess.run(tf.assign(bias_var,bias_values)) + + #Write fused weights to ckpt file + tf.logging.info('Saving new checkpoint at '+FLAGS.checkpoint+'_bnfused') + saver.save(sess, FLAGS.checkpoint+'_bnfused') + +def main(_): + + # Create the model and load its weights. + fold_batch_norm(FLAGS.wanted_words, FLAGS.sample_rate, + FLAGS.clip_duration_ms, FLAGS.window_size_ms, + FLAGS.window_stride_ms, FLAGS.dct_coefficient_count, + FLAGS.model_architecture, FLAGS.model_size_info) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--data_url', + type=str, + # pylint: disable=line-too-long + default='http://download.tensorflow.org/data/speech_commands_v0.02.tar.gz', + # pylint: enable=line-too-long + help='Location of speech training data archive on the web.') + parser.add_argument( + '--data_dir', + type=str, + default='/tmp/speech_dataset/', + help="""\ + Where to download the speech training data to. + """) + parser.add_argument( + '--silence_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be silence. + """) + parser.add_argument( + '--unknown_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be unknown words. + """) + parser.add_argument( + '--testing_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a test set.') + parser.add_argument( + '--validation_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a validation set.') + parser.add_argument( + '--sample_rate', + type=int, + default=16000, + help='Expected sample rate of the wavs',) + parser.add_argument( + '--clip_duration_ms', + type=int, + default=1000, + help='Expected duration in milliseconds of the wavs',) + parser.add_argument( + '--window_size_ms', + type=float, + default=30.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--window_stride_ms', + type=float, + default=10.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--dct_coefficient_count', + type=int, + default=40, + help='How many bins to use for the MFCC fingerprint',) + parser.add_argument( + '--batch_size', + type=int, + default=100, + help='How many items to train with at once',) + parser.add_argument( + '--wanted_words', + type=str, + default='yes,no,up,down,left,right,on,off,stop,go', + help='Words to use (others will be added to an unknown label)',) + parser.add_argument( + '--checkpoint', + type=str, + default='', + help='Checkpoint to load the weights from.') + parser.add_argument( + '--model_architecture', + type=str, + default='dnn', + help='What model architecture to use') + parser.add_argument( + '--model_size_info', + type=int, + nargs="+", + default=[128,128,128], + help='Model dimensions - different for various models') + + FLAGS, unparsed = parser.parse_known_args() + tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/freeze.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/freeze.py new file mode 100644 index 0000000000000000000000000000000000000000..12541b8253111d2e16f228c5b262fb7fb347c2ac --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/freeze.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017 Arm Inc. All Rights Reserved. +# Added model dimensions as command line argument for generating the pb file +# +# + +"""Converts a trained checkpoint into a frozen model for mobile inference. + +Once you've trained a model using the `train.py` script, you can use this tool +to convert it into a binary GraphDef file that can be loaded into the Android, +iOS, or Raspberry Pi example code. Here's an example of how to run it: + +bazel run tensorflow/examples/speech_commands/freeze -- \ +--sample_rate=16000 --dct_coefficient_count=40 --window_size_ms=20 \ +--window_stride_ms=10 --clip_duration_ms=1000 \ +--model_architecture=conv \ +--checkpoint=/tmp/speech_commands_train/conv.ckpt-1300 \ +--output_file=/tmp/my_frozen_graph.pb + +One thing to watch out for is that you need to pass in the same arguments for +`sample_rate` and other command line variables here as you did for the training +script. + +The resulting graph has an input for WAV-encoded data named 'wav_data', one for +raw PCM data (as floats in the range -1.0 to 1.0) called 'decoded_sample_data', +and the output is called 'labels_softmax'. + +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import argparse +import os.path +import sys + +import tensorflow as tf + +from tensorflow.contrib.framework.python.ops import audio_ops as contrib_audio +import input_data +import models +from tensorflow.python.framework import graph_util + +FLAGS = None + + +def create_inference_graph(wanted_words, sample_rate, clip_duration_ms, + clip_stride_ms, window_size_ms, window_stride_ms, + dct_coefficient_count, model_architecture, model_size_info): + """Creates an audio model with the nodes needed for inference. + + Uses the supplied arguments to create a model, and inserts the input and + output nodes that are needed to use the graph for inference. + + Args: + wanted_words: Comma-separated list of the words we're trying to recognize. + sample_rate: How many samples per second are in the input audio files. + clip_duration_ms: How many samples to analyze for the audio pattern. + clip_stride_ms: How often to run recognition. Useful for models with cache. + window_size_ms: Time slice duration to estimate frequencies from. + window_stride_ms: How far apart time slices should be. + dct_coefficient_count: Number of frequency bands to analyze. + model_architecture: Name of the kind of model to generate. + """ + + words_list = input_data.prepare_words_list(wanted_words.split(',')) + model_settings = models.prepare_model_settings( + len(words_list), sample_rate, clip_duration_ms, window_size_ms, + window_stride_ms, dct_coefficient_count) + runtime_settings = {'clip_stride_ms': clip_stride_ms} + + wav_data_placeholder = tf.placeholder(tf.string, [], name='wav_data') + decoded_sample_data = contrib_audio.decode_wav( + wav_data_placeholder, + desired_channels=1, + desired_samples=model_settings['desired_samples'], + name='decoded_sample_data') + spectrogram = contrib_audio.audio_spectrogram( + decoded_sample_data.audio, + window_size=model_settings['window_size_samples'], + stride=model_settings['window_stride_samples'], + magnitude_squared=True) + fingerprint_input = contrib_audio.mfcc( + spectrogram, + decoded_sample_data.sample_rate, + dct_coefficient_count=dct_coefficient_count) + fingerprint_frequency_size = model_settings['dct_coefficient_count'] + fingerprint_time_size = model_settings['spectrogram_length'] + reshaped_input = tf.reshape(fingerprint_input, [ + -1, fingerprint_time_size * fingerprint_frequency_size + ]) + + logits = models.create_model( + reshaped_input, model_settings, model_architecture, model_size_info, + is_training=False, runtime_settings=runtime_settings) + + # Create an output to use for inference. + tf.nn.softmax(logits, name='labels_softmax') + + +def main(_): + + # Create the model and load its weights. + sess = tf.InteractiveSession(config=npu_config_proto()) + create_inference_graph(FLAGS.wanted_words, FLAGS.sample_rate, + FLAGS.clip_duration_ms, FLAGS.clip_stride_ms, + FLAGS.window_size_ms, FLAGS.window_stride_ms, + FLAGS.dct_coefficient_count, FLAGS.model_architecture, + FLAGS.model_size_info) + models.load_variables_from_checkpoint(sess, FLAGS.checkpoint) + + # Turn all the variables into inline constants inside the graph and save it. + frozen_graph_def = graph_util.convert_variables_to_constants( + sess, sess.graph_def, ['labels_softmax']) + tf.train.write_graph( + frozen_graph_def, + os.path.dirname(FLAGS.output_file), + os.path.basename(FLAGS.output_file), + as_text=False) + tf.logging.info('Saved frozen graph to %s', FLAGS.output_file) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--sample_rate', + type=int, + default=16000, + help='Expected sample rate of the wavs',) + parser.add_argument( + '--clip_duration_ms', + type=int, + default=1000, + help='Expected duration in milliseconds of the wavs',) + parser.add_argument( + '--clip_stride_ms', + type=int, + default=30, + help='How often to run recognition. Useful for models with cache.',) + parser.add_argument( + '--window_size_ms', + type=float, + default=30.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--window_stride_ms', + type=float, + default=10.0, + help='How long the stride is between spectrogram timeslices',) + parser.add_argument( + '--dct_coefficient_count', + type=int, + default=40, + help='How many bins to use for the MFCC fingerprint',) + parser.add_argument( + '--checkpoint', + type=str, + default='', + help='If specified, restore this pretrained model before any training.') + parser.add_argument( + '--model_architecture', + type=str, + default='dnn', + help='What model architecture to use') + parser.add_argument( + '--model_size_info', + type=int, + nargs="+", + default=[128,128,128], + help='Model dimensions - different for various models') + parser.add_argument( + '--wanted_words', + type=str, + default='yes,no,up,down,left,right,on,off,stop,go', + help='Words to use (others will be added to an unknown label)',) + parser.add_argument( + '--output_file', type=str, help='Where to save the frozen graph.') + FLAGS, unparsed = parser.parse_known_args() + tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/input_data.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/input_data.py new file mode 100644 index 0000000000000000000000000000000000000000..b7ccff31f86b7f04f3e2b67c11360d5a52b27891 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/input_data.py @@ -0,0 +1,692 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""Model definitions for simple speech recognition. + +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * +from npu_bridge.estimator.npu import * +import hashlib +import math +import os.path +import random +import re +import sys +import tarfile + +import numpy as np +from six.moves import urllib +from six.moves import xrange # pylint: disable=redefined-builtin +import tensorflow as tf + +from tensorflow.contrib.framework.python.ops import audio_ops as contrib_audio +from tensorflow.python.ops import io_ops +from tensorflow.python.platform import gfile +from tensorflow.python.util import compat +import time + +MAX_NUM_WAVS_PER_CLASS = 2**27 - 1 # ~134M +SILENCE_LABEL = '_silence_' +SILENCE_INDEX = 0 +UNKNOWN_WORD_LABEL = '_unknown_' +UNKNOWN_WORD_INDEX = 1 +BACKGROUND_NOISE_DIR_NAME = '_background_noise_' +RANDOM_SEED = 59185 + + +def prepare_words_list(wanted_words): + """Prepends common tokens to the custom word list. + + Args: + wanted_words: List of strings containing the custom words. + + Returns: + List with the standard silence and unknown tokens added. + """ + return [SILENCE_LABEL, UNKNOWN_WORD_LABEL] + wanted_words + + +def which_set(filename, validation_percentage, testing_percentage): + """Determines which data partition the file should belong to. + + We want to keep files in the same training, validation, or testing sets even + if new ones are added over time. This makes it less likely that testing + samples will accidentally be reused in training when long runs are restarted + for example. To keep this stability, a hash of the filename is taken and used + to determine which set it should belong to. This determination only depends on + the name and the set proportions, so it won't change as other files are added. + + It's also useful to associate particular files as related (for example words + spoken by the same person), so anything after '_nohash_' in a filename is + ignored for set determination. This ensures that 'bobby_nohash_0.wav' and + 'bobby_nohash_1.wav' are always in the same set, for example. + + Args: + filename: File path of the data sample. + validation_percentage: How much of the data set to use for validation. + testing_percentage: How much of the data set to use for testing. + + Returns: + String, one of 'training', 'validation', or 'testing'. + """ + base_name = os.path.basename(filename) + # We want to ignore anything after '_nohash_' in the file name when + # deciding which set to put a wav in, so the data set creator has a way of + # grouping wavs that are close variations of each other. + hash_name = re.sub(r'_nohash_.*$', '', base_name) + # This looks a bit magical, but we need to decide whether this file should + # go into the training, testing, or validation sets, and we want to keep + # existing files in the same set even if more files are subsequently + # added. + # To do that, we need a stable way of deciding based on just the file name + # itself, so we do a hash of that and then use that to generate a + # probability value that we use to assign it. + hash_name_hashed = hashlib.sha1(compat.as_bytes(hash_name)).hexdigest() + percentage_hash = ((int(hash_name_hashed, 16) % + (MAX_NUM_WAVS_PER_CLASS + 1)) * + (100.0 / MAX_NUM_WAVS_PER_CLASS)) + if percentage_hash < validation_percentage: + result = 'validation' + elif percentage_hash < (testing_percentage + validation_percentage): + result = 'testing' + else: + result = 'training' + return result + + +def load_wav_file(filename): + """Loads an audio file and returns a float PCM-encoded array of samples. + + Args: + filename: Path to the .wav file to load. + + Returns: + Numpy array holding the sample data as floats between -1.0 and 1.0. + """ + with tf.Session(graph=tf.Graph(), config=npu_config_proto()) as sess: + wav_filename_placeholder = tf.placeholder(tf.string, []) + wav_loader = io_ops.read_file(wav_filename_placeholder) + wav_decoder = contrib_audio.decode_wav(wav_loader, desired_channels=1) + return sess.run( + wav_decoder, + feed_dict={wav_filename_placeholder: filename}).audio.flatten() + + +def save_wav_file(filename, wav_data, sample_rate): + """Saves audio sample data to a .wav audio file. + + Args: + filename: Path to save the file to. + wav_data: 2D array of float PCM-encoded audio data. + sample_rate: Samples per second to encode in the file. + """ + with tf.Session(graph=tf.Graph(), config=npu_config_proto()) as sess: + wav_filename_placeholder = tf.placeholder(tf.string, []) + sample_rate_placeholder = tf.placeholder(tf.int32, []) + wav_data_placeholder = tf.placeholder(tf.float32, [None, 1]) + wav_encoder = contrib_audio.encode_wav(wav_data_placeholder, + sample_rate_placeholder) + wav_saver = io_ops.write_file(wav_filename_placeholder, wav_encoder) + sess.run( + wav_saver, + feed_dict={ + wav_filename_placeholder: filename, + sample_rate_placeholder: sample_rate, + wav_data_placeholder: np.reshape(wav_data, (-1, 1)) + }) + + +class AudioProcessor(object): + """Handles loading, partitioning, and preparing audio training data.""" + + def __init__(self, data_url, data_dir, silence_percentage, unknown_percentage, + wanted_words, validation_percentage, testing_percentage, + model_settings, sess): + self.data_dir = data_dir + self.maybe_download_and_extract_dataset(data_url, data_dir) + self.prepare_data_index(silence_percentage, unknown_percentage, + wanted_words, validation_percentage, + testing_percentage) + self.prepare_background_data() + self.prepare_processing_graph(model_settings) + self.model_settings = model_settings + self.sess = sess + + def maybe_download_and_extract_dataset(self, data_url, dest_directory): + """Download and extract data set tar file. + + If the data set we're using doesn't already exist, this function + downloads it from the TensorFlow.org website and unpacks it into a + directory. + If the data_url is none, don't download anything and expect the data + directory to contain the correct files already. + + Args: + data_url: Web location of the tar file containing the data set. + dest_directory: File path to extract data to. + """ + if not data_url: + return + if not os.path.exists(dest_directory): + os.makedirs(dest_directory) + filename = data_url.split('/')[-1] + filepath = os.path.join(dest_directory, filename) + if not os.path.exists(filepath): + + def _progress(count, block_size, total_size): + sys.stdout.write( + '\r>> Downloading %s %.1f%%' % + (filename, float(count * block_size) / float(total_size) * 100.0)) + sys.stdout.flush() + + try: + filepath, _ = urllib.request.urlretrieve(data_url, filepath, _progress) + except: + tf.logging.error('Failed to download URL: %s to folder: %s', data_url, + filepath) + tf.logging.error('Please make sure you have enough free space and' + ' an internet connection') + raise + print() + statinfo = os.stat(filepath) + tf.logging.info('Successfully downloaded %s (%d bytes)', filename, + statinfo.st_size) + tarfile.open(filepath, 'r:gz').extractall(dest_directory) + + def prepare_data_index(self, silence_percentage, unknown_percentage, + wanted_words, validation_percentage, + testing_percentage): + """Prepares a list of the samples organized by set and label. + + The training loop needs a list of all the available data, organized by + which partition it should belong to, and with ground truth labels attached. + This function analyzes the folders below the `data_dir`, figures out the + right + labels for each file based on the name of the subdirectory it belongs to, + and uses a stable hash to assign it to a data set partition. + + Args: + silence_percentage: How much of the resulting data should be background. + unknown_percentage: How much should be audio outside the wanted classes. + wanted_words: Labels of the classes we want to be able to recognize. + validation_percentage: How much of the data set to use for validation. + testing_percentage: How much of the data set to use for testing. + + Returns: + Dictionary containing a list of file information for each set partition, + and a lookup map for each class to determine its numeric index. + + Raises: + Exception: If expected files are not found. + """ + # Make sure the shuffling and picking of unknowns is deterministic. + random.seed(RANDOM_SEED) + wanted_words_index = {} + for index, wanted_word in enumerate(wanted_words): + wanted_words_index[wanted_word] = index + 2 + self.data_index = {'validation': [], 'testing': [], 'training': []} + unknown_index = {'validation': [], 'testing': [], 'training': []} + all_words = {} + # Look through all the subfolders to find audio samples + search_path = os.path.join(self.data_dir, '*', '*.wav') + for wav_path in gfile.Glob(search_path): + _, word = os.path.split(os.path.dirname(wav_path)) + word = word.lower() + # Treat the '_background_noise_' folder as a special case, since we expect + # it to contain long audio samples we mix in to improve training. + if word == BACKGROUND_NOISE_DIR_NAME: + continue + all_words[word] = True + set_index = which_set(wav_path, validation_percentage, testing_percentage) + # If it's a known class, store its detail, otherwise add it to the list + # we'll use to train the unknown label. + if word in wanted_words_index: + self.data_index[set_index].append({'label': word, 'file': wav_path}) + else: + unknown_index[set_index].append({'label': word, 'file': wav_path}) + if not all_words: + raise Exception('No .wavs found at ' + search_path) + for index, wanted_word in enumerate(wanted_words): + if wanted_word not in all_words: + raise Exception('Expected to find ' + wanted_word + + ' in labels but only found ' + + ', '.join(all_words.keys())) + # We need an arbitrary file to load as the input for the silence samples. + # It's multiplied by zero later, so the content doesn't matter. + silence_wav_path = self.data_index['training'][0]['file'] + for set_index in ['validation', 'testing', 'training']: + set_size = len(self.data_index[set_index]) + silence_size = int(math.ceil(set_size * silence_percentage / 100)) + for _ in range(silence_size): + self.data_index[set_index].append({ + 'label': SILENCE_LABEL, + 'file': silence_wav_path + }) + # Pick some unknowns to add to each partition of the data set. + random.shuffle(unknown_index[set_index]) + unknown_size = int(math.ceil(set_size * unknown_percentage / 100)) + self.data_index[set_index].extend(unknown_index[set_index][:unknown_size]) + # Make sure the ordering is random. + for set_index in ['validation', 'testing', 'training']: + random.shuffle(self.data_index[set_index]) + # Prepare the rest of the result data structure. + self.words_list = prepare_words_list(wanted_words) + self.word_to_index = {} + for word in all_words: + if word in wanted_words_index: + self.word_to_index[word] = wanted_words_index[word] + else: + self.word_to_index[word] = UNKNOWN_WORD_INDEX + self.word_to_index[SILENCE_LABEL] = SILENCE_INDEX + + def prepare_background_data(self): + """Searches a folder for background noise audio, and loads it into memory. + + It's expected that the background audio samples will be in a subdirectory + named '_background_noise_' inside the 'data_dir' folder, as .wavs that match + the sample rate of the training data, but can be much longer in duration. + + If the '_background_noise_' folder doesn't exist at all, this isn't an + error, it's just taken to mean that no background noise augmentation should + be used. If the folder does exist, but it's empty, that's treated as an + error. + + Returns: + List of raw PCM-encoded audio samples of background noise. + + Raises: + Exception: If files aren't found in the folder. + """ + self.background_data = [] + background_dir = os.path.join(self.data_dir, BACKGROUND_NOISE_DIR_NAME) + if not os.path.exists(background_dir): + return self.background_data + with tf.Session(graph=tf.Graph(), config=npu_config_proto()) as sess: + wav_filename_placeholder = tf.placeholder(tf.string, [], name='wav_filename_placeholder') + wav_loader = io_ops.read_file(wav_filename_placeholder) + wav_decoder = contrib_audio.decode_wav(wav_loader, desired_channels=1) + search_path = os.path.join(self.data_dir, BACKGROUND_NOISE_DIR_NAME, + '*.wav') + for wav_path in gfile.Glob(search_path): + wav_data = sess.run( + wav_decoder, + feed_dict={wav_filename_placeholder: wav_path}).audio.flatten() + self.background_data.append(wav_data) + if not self.background_data: + raise Exception('No background wav files were found in ' + search_path) + + def prepare_processing_graph(self, model_settings): + """Builds a TensorFlow graph to apply the input distortions. + + Creates a graph that loads a WAVE file, decodes it, scales the volume, + shifts it in time, adds in background noise, calculates a spectrogram, and + then builds an MFCC fingerprint from that. + + This must be called with an active TensorFlow session running, and it + creates multiple placeholder inputs, and one output: + + - wav_filename_placeholder_: Filename of the WAV to load. + - foreground_volume_placeholder_: How loud the main clip should be. + - time_shift_padding_placeholder_: Where to pad the clip. + - time_shift_offset_placeholder_: How much to move the clip in time. + - background_data_placeholder_: PCM sample data for background noise. + - background_volume_placeholder_: Loudness of mixed-in background. + - mfcc_: Output 2D fingerprint of processed audio. + + Args: + model_settings: Information about the current model being trained. + """ + desired_samples = model_settings['desired_samples'] + self.wav_filename_placeholder_ = tf.placeholder(tf.string, [], name='wav_filename_placeholder_') + wav_loader = io_ops.read_file(self.wav_filename_placeholder_) + wav_decoder = contrib_audio.decode_wav( + wav_loader, desired_channels=1, desired_samples=desired_samples) + # Allow the audio sample's volume to be adjusted. + self.foreground_volume_placeholder_ = tf.placeholder(tf.float32, [], name='foreground_volume_placeholder_') + scaled_foreground = tf.multiply(wav_decoder.audio, + self.foreground_volume_placeholder_) + # Shift the sample's start position, and pad any gaps with zeros. + self.time_shift_padding_placeholder_ = tf.placeholder(tf.int32, [2, 2], name='time_shift_padding_placeholder_') + self.time_shift_offset_placeholder_ = tf.placeholder(tf.int32, [2], name='time_shift_offset_placeholder_') + padded_foreground = tf.pad( + scaled_foreground, + self.time_shift_padding_placeholder_, + mode='CONSTANT') + sliced_foreground = tf.slice(padded_foreground, + self.time_shift_offset_placeholder_, + [desired_samples, -1]) + # Mix in background noise. + self.background_data_placeholder_ = tf.placeholder(tf.float32, + [desired_samples, 1], name='background_data_placeholder_') + self.background_volume_placeholder_ = tf.placeholder(tf.float32, [], name='background_volume_placeholder_') + background_mul = tf.multiply(self.background_data_placeholder_, + self.background_volume_placeholder_) + background_add = tf.add(background_mul, sliced_foreground) + background_clamp = tf.clip_by_value(background_add, -1.0, 1.0) + # Run the spectrogram and MFCC ops to get a 2D 'fingerprint' of the audio. + spectrogram = contrib_audio.audio_spectrogram( + background_clamp, + window_size=model_settings['window_size_samples'], + stride=model_settings['window_stride_samples'], + magnitude_squared=True) + self.mfcc_ = contrib_audio.mfcc( + spectrogram, + wav_decoder.sample_rate, + dct_coefficient_count=model_settings['dct_coefficient_count']) + #################### + # self.mfcc_ = util.set_graph_exec_config(self.mfcc_,dynamic_input=True, + # dynamic_graph_execute_mode='dynamic_execute', + # dynamic_inputs_shape_range='data:[100~16000,1~490],[],[16000,1],[],[],[2],[2,2]') + #################### + def set_size(self, mode): + """Calculates the number of samples in the dataset partition. + + Args: + mode: Which partition, must be 'training', 'validation', or 'testing'. + + Returns: + Number of samples in the partition. + """ + return len(self.data_index[mode]) + + def get_data(self, how_many, offset, model_settings, background_frequency, + background_volume_range, time_shift, mode, sess): + """Gather samples from the data set, applying transformations as needed. + + When the mode is 'training', a random selection of samples will be returned, + otherwise the first N clips in the partition will be used. This ensures that + validation always uses the same samples, reducing noise in the metrics. + + Args: + how_many: Desired number of samples to return. -1 means the entire + contents of this partition. + offset: Where to start when fetching deterministically. + model_settings: Information about the current model being trained. + background_frequency: How many clips will have background noise, 0.0 to + 1.0. + background_volume_range: How loud the background noise will be. + time_shift: How much to randomly shift the clips by in time. + mode: Which partition to use, must be 'training', 'validation', or + 'testing'. + sess: TensorFlow session that was active when processor was created. + + Returns: + List of sample data for the transformed samples, and list of labels in + one-hot form. + """ + # Pick one of the partitions to choose samples from. + candidates = self.data_index[mode] + if how_many == -1: + sample_count = len(candidates) + else: + sample_count = max(0, min(how_many, len(candidates) - offset)) + # Data and labels will be populated and returned. + data = np.zeros((sample_count, model_settings['fingerprint_size'])) + labels = np.zeros((sample_count, model_settings['label_count'])) + desired_samples = model_settings['desired_samples'] + use_background = self.background_data and (mode == 'training') + pick_deterministically = (mode != 'training') + # Use the processing graph we created earlier to repeatedly to generate the + # final output sample data we'll use in training. + for i in xrange(offset, offset + sample_count): + # Pick which audio sample to use. + if how_many == -1 or pick_deterministically: + sample_index = i + else: + sample_index = np.random.randint(len(candidates)) + sample = candidates[sample_index] + # If we're time shifting, set up the offset for this sample. + if time_shift > 0: + time_shift_amount = np.random.randint(-time_shift, time_shift) + else: + time_shift_amount = 0 + if time_shift_amount > 0: + time_shift_padding = [[time_shift_amount, 0], [0, 0]] + time_shift_offset = [0, 0] + else: + time_shift_padding = [[0, -time_shift_amount], [0, 0]] + time_shift_offset = [-time_shift_amount, 0] + input_dict = { + self.wav_filename_placeholder_: sample['file'], + self.time_shift_padding_placeholder_: time_shift_padding, + self.time_shift_offset_placeholder_: time_shift_offset, + } + # Choose a section of background noise to mix in. + if use_background: + background_index = np.random.randint(len(self.background_data)) + background_samples = self.background_data[background_index] + background_offset = np.random.randint( + 0, len(background_samples) - model_settings['desired_samples']) + background_clipped = background_samples[background_offset:( + background_offset + desired_samples)] + background_reshaped = background_clipped.reshape([desired_samples, 1]) + if np.random.uniform(0, 1) < background_frequency: + background_volume = np.random.uniform(0, background_volume_range) + else: + background_volume = 0 + else: + background_reshaped = np.zeros([desired_samples, 1]) + background_volume = 0 + input_dict[self.background_data_placeholder_] = background_reshaped + input_dict[self.background_volume_placeholder_] = background_volume + # If we want silence, mute out the main sample but leave the background. + if sample['label'] == SILENCE_LABEL: + input_dict[self.foreground_volume_placeholder_] = 0 + else: + input_dict[self.foreground_volume_placeholder_] = 1 + # Run the graph to produce the output audio. + data[i - offset, :] = sess.run(self.mfcc_, feed_dict=input_dict).flatten() + label_index = self.word_to_index[sample['label']] + labels[i - offset, label_index] = 1 + return data, labels + + def parse_dataset_data(self, file, label_str, label_index): + sample_file = file.decode() + label = label_str.decode() + + fingerprint_size = self.model_settings['fingerprint_size'] + label_count = self.model_settings['label_count'] + desired_samples = self.model_settings['desired_samples'] + + background_frequency = self.background_frequency + background_volume_range = self.background_volume_range + time_shift = self.time_shift + + mode = 'training' + + data = np.zeros(fingerprint_size, dtype=np.float32) + labels = np.zeros(label_count, dtype=np.float32) + + use_background = self.background_data and (mode == 'training') + pick_deterministically = (mode != 'training') + + # If we're time shifting, set up the offset for this sample. + if time_shift > 0: + time_shift_amount = np.random.randint(-time_shift, time_shift) + else: + time_shift_amount = 0 + if time_shift_amount > 0: + time_shift_padding = [[time_shift_amount, 0], [0, 0]] + time_shift_offset = [0, 0] + else: + time_shift_padding = [[0, -time_shift_amount], [0, 0]] + time_shift_offset = [-time_shift_amount, 0] + input_dict = { + self.wav_filename_placeholder_: sample_file, + self.time_shift_padding_placeholder_: time_shift_padding, + self.time_shift_offset_placeholder_: time_shift_offset, + } + # Choose a section of background noise to mix in. + if use_background: + background_index = np.random.randint(len(self.background_data)) + background_samples = self.background_data[background_index] + background_offset = np.random.randint( + 0, len(background_samples) - desired_samples) + background_clipped = background_samples[background_offset:( + background_offset + desired_samples)] + background_reshaped = background_clipped.reshape([desired_samples, 1]) + if np.random.uniform(0, 1) < background_frequency: + background_volume = np.random.uniform(0, background_volume_range) + else: + background_volume = 0 + else: + background_reshaped = np.zeros([desired_samples, 1]) + background_volume = 0 + input_dict[self.background_data_placeholder_] = background_reshaped + input_dict[self.background_volume_placeholder_] = background_volume + # If we want silence, mute out the main sample but leave the background. + if label == SILENCE_LABEL: + input_dict[self.foreground_volume_placeholder_] = 0 + else: + input_dict[self.foreground_volume_placeholder_] = 1 + # Run the graph to produce the output audio. + mfcc_res = self.sess.run(self.mfcc_, feed_dict=input_dict).flatten() + + #label_index = self.word_to_index[sample['label']] + labels[label_index] = 1 + data[:] = mfcc_res + + return data, labels + + def create_dataset(self, steps, how_many, offset, model_settings, background_frequency, + background_volume_range, time_shift, mode, sess): + label_indexs = [] + sample_files = [] + labels = [] + start= time.time() + candidates = self.data_index[mode] + print('**** length of train candidates: {}'.format(len(candidates))) + + for i in range(len(candidates)): + sample = candidates[i] + sample_files.append(sample['file']) + labels.append(sample['label']) + label_index = int(self.word_to_index[sample['label']]) + label_indexs.append(label_index) + + self.background_frequency = background_frequency + self.background_volume_range = background_volume_range + self.time_shift = time_shift + print('==== background_frequency: {} background_volume_range: {} time_shift: {}'.format(self.background_frequency, self.background_volume_range, self.time_shift)) + + dataset = tf.data.Dataset.from_tensor_slices((sample_files, labels, label_indexs)) + dataset = dataset.shuffle(buffer_size=30000) + repeat_cnt = steps // (len(candidates) // how_many) + 1 + dataset = dataset.repeat(repeat_cnt) + #dataset = dataset.shuffle(buffer_size=30000) + dataset = dataset.map(lambda sample_file, label, label_index:tf.py_func(self.parse_dataset_data, inp=[sample_file, label, label_index], Tout=[tf.float32, tf.float32]), + num_parallel_calls=16) + dataset = dataset.prefetch(buffer_size=tf.contrib.data.AUTOTUNE) + dataset = dataset.batch(how_many) + + dataset_end = time.time() + print('**** dataset create duration: %.6f' % (dataset_end-start)) + + return dataset + + + def get_wav_files(self, how_many, offset, model_settings, mode): + """Return wav_file names and labels from train/val/test sets. + """ + # Pick one of the partitions to choose samples from. + candidates = self.data_index[mode] + if how_many == -1: + sample_count = len(candidates) + else: + sample_count = max(0, min(how_many, len(candidates) - offset)) + pick_deterministically = (mode != 'training') + wav_files = [] + labels = np.zeros((sample_count, model_settings['label_count'])) + for i in xrange(offset, offset + sample_count): + # Pick which audio sample to use. + if how_many == -1 or pick_deterministically: + sample_index = i + else: + sample_index = np.random.randint(len(candidates)) + sample = candidates[sample_index] + if sample['label'] == SILENCE_LABEL: + wav_files.append('silence.wav') + else: + wav_files.append(sample['file']) + label_index = self.word_to_index[sample['label']] + labels[i - offset, label_index] = 1 + return wav_files, labels + + + def get_unprocessed_data(self, how_many, model_settings, mode): + """Retrieve sample data for the given partition, with no transformations. + + Args: + how_many: Desired number of samples to return. -1 means the entire + contents of this partition. + model_settings: Information about the current model being trained. + mode: Which partition to use, must be 'training', 'validation', or + 'testing'. + + Returns: + List of sample data for the samples, and list of labels in one-hot form. + """ + candidates = self.data_index[mode] + if how_many == -1: + sample_count = len(candidates) + else: + sample_count = how_many + desired_samples = model_settings['desired_samples'] + words_list = self.words_list + data = np.zeros((sample_count, desired_samples)) + labels = [] + with tf.Session(graph=tf.Graph(), config=npu_config_proto()) as sess: + wav_filename_placeholder = tf.placeholder(tf.string, []) + wav_loader = io_ops.read_file(wav_filename_placeholder) + wav_decoder = contrib_audio.decode_wav( + wav_loader, desired_channels=1, desired_samples=desired_samples) + foreground_volume_placeholder = tf.placeholder(tf.float32, []) + scaled_foreground = tf.multiply(wav_decoder.audio, + foreground_volume_placeholder) + for i in range(sample_count): + if how_many == -1: + sample_index = i + else: + sample_index = np.random.randint(len(candidates)) + sample = candidates[sample_index] + input_dict = {wav_filename_placeholder: sample['file']} + if sample['label'] == SILENCE_LABEL: + input_dict[foreground_volume_placeholder] = 0 + else: + input_dict[foreground_volume_placeholder] = 1 + data[i, :] = sess.run(scaled_foreground, feed_dict=input_dict).flatten() + label_index = self.word_to_index[sample['label']] + labels.append(words_list[label_index]) + return data, labels + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/label_wav.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/label_wav.py new file mode 100644 index 0000000000000000000000000000000000000000..db4c25f66186a63c11315e67636e0e329d4367c0 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/label_wav.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +r"""Runs a trained audio graph against a WAVE file and reports the results. + +The model, labels and .wav file specified in the arguments will be loaded, and +then the predictions from running the model against the audio data will be +printed to the console. This is a useful script for sanity checking trained +models, and as an example of how to use an audio model from Python. + +Here's an example of running it: + +python tensorflow/examples/speech_commands/label_wav.py \ +--graph=/tmp/my_frozen_graph.pb \ +--labels=/tmp/speech_commands_train/conv_labels.txt \ +--wav=/tmp/speech_dataset/left/a5d485dc_nohash_0.wav + +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import argparse +import sys + +import tensorflow as tf + +# pylint: disable=unused-import +from tensorflow.contrib.framework.python.ops import audio_ops as contrib_audio +# pylint: enable=unused-import + +FLAGS = None + + +def load_graph(filename): + """Unpersists graph from file as default graph.""" + with tf.gfile.FastGFile(filename, 'rb') as f: + graph_def = tf.GraphDef() + graph_def.ParseFromString(f.read()) + tf.import_graph_def(graph_def, name='') + + +def load_labels(filename): + """Read in labels, one label per line.""" + return [line.rstrip() for line in tf.gfile.GFile(filename)] + + +def run_graph(wav_data, labels, input_layer_name, output_layer_name, + num_top_predictions): + """Runs the audio data through the graph and prints predictions.""" + with tf.Session(config=npu_config_proto()) as sess: + # Feed the audio data as input to the graph. + # predictions will contain a two-dimensional array, where one + # dimension represents the input image count, and the other has + # predictions per class + softmax_tensor = sess.graph.get_tensor_by_name(output_layer_name) + predictions, = sess.run(softmax_tensor, {input_layer_name: wav_data}) + + # Sort to show labels in order of confidence + top_k = predictions.argsort()[-num_top_predictions:][::-1] + for node_id in top_k: + human_string = labels[node_id] + score = predictions[node_id] + print('%s (score = %.5f)' % (human_string, score)) + + return 0 + + +def label_wav(wav, labels, graph, input_name, output_name, how_many_labels): + """Loads the model and labels, and runs the inference to print predictions.""" + if not wav or not tf.gfile.Exists(wav): + tf.logging.fatal('Audio file does not exist %s', wav) + + if not labels or not tf.gfile.Exists(labels): + tf.logging.fatal('Labels file does not exist %s', labels) + + if not graph or not tf.gfile.Exists(graph): + tf.logging.fatal('Graph file does not exist %s', graph) + + labels_list = load_labels(labels) + + # load graph, which is stored in the default session + load_graph(graph) + + with open(wav, 'rb') as wav_file: + wav_data = wav_file.read() + + run_graph(wav_data, labels_list, input_name, output_name, how_many_labels) + + +def main(_): + """Entry point for script, converts flags to arguments.""" + label_wav(FLAGS.wav, FLAGS.labels, FLAGS.graph, FLAGS.input_name, + FLAGS.output_name, FLAGS.how_many_labels) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--wav', type=str, default='', help='Audio file to be identified.') + parser.add_argument( + '--graph', type=str, default='', help='Model to use for identification.') + parser.add_argument( + '--labels', type=str, default='', help='Path to file containing labels.') + parser.add_argument( + '--input_name', + type=str, + default='wav_data:0', + help='Name of WAVE data input node in model.') + parser.add_argument( + '--output_name', + type=str, + default='labels_softmax:0', + help='Name of node outputting a prediction in the model.') + parser.add_argument( + '--how_many_labels', + type=int, + default=3, + help='Number of results to show.') + + FLAGS, unparsed = parser.parse_known_args() + tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/models.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/models.py new file mode 100644 index 0000000000000000000000000000000000000000..bfcc134f0723c6b6e5206c69c1264f28cc4436a5 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/models.py @@ -0,0 +1,1207 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017 Arm Inc. All Rights Reserved. +# Added new model definitions for speech command recognition used in +# the paper: https://arxiv.org/pdf/1711.07128.pdf +# +# + +"""Model definitions for simple speech recognition. + +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import math + +import tensorflow as tf +import tensorflow.contrib.slim as slim +from tensorflow.contrib.layers.python.layers import layers +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import init_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import nn_ops +from tensorflow.python.ops import rnn_cell_impl +from tensorflow.python.ops import variable_scope as vs + +def prepare_model_settings(label_count, sample_rate, clip_duration_ms, + window_size_ms, window_stride_ms, + dct_coefficient_count): + """Calculates common settings needed for all models. + + Args: + label_count: How many classes are to be recognized. + sample_rate: Number of audio samples per second. + clip_duration_ms: Length of each audio clip to be analyzed. + window_size_ms: Duration of frequency analysis window. + window_stride_ms: How far to move in time between frequency windows. + dct_coefficient_count: Number of frequency bins to use for analysis. + + Returns: + Dictionary containing common settings. + """ + desired_samples = int(sample_rate * clip_duration_ms / 1000) + window_size_samples = int(sample_rate * window_size_ms / 1000) + window_stride_samples = int(sample_rate * window_stride_ms / 1000) + length_minus_window = (desired_samples - window_size_samples) + if length_minus_window < 0: + spectrogram_length = 0 + else: + spectrogram_length = 1 + int(length_minus_window / window_stride_samples) + fingerprint_size = dct_coefficient_count * spectrogram_length + print('==== model_settings:') + print('==== desired_samples: {} window_size_samples: {} window_stride_samples: {} spectrogram_length: {}'.format(desired_samples, window_size_samples, window_stride_samples, spectrogram_length) ) + print('==== dct_coefficient_count: {} fingerprint_size: {} label_count: {} sample_rate: {}'.format(dct_coefficient_count, fingerprint_size, label_count, sample_rate) ) + + return { + 'desired_samples': desired_samples, + 'window_size_samples': window_size_samples, + 'window_stride_samples': window_stride_samples, + 'spectrogram_length': spectrogram_length, + 'dct_coefficient_count': dct_coefficient_count, + 'fingerprint_size': fingerprint_size, + 'label_count': label_count, + 'sample_rate': sample_rate, + } + + +def create_model(fingerprint_input, model_settings, model_architecture, + model_size_info, is_training, runtime_settings=None): + """Builds a model of the requested architecture compatible with the settings. + + There are many possible ways of deriving predictions from a spectrogram + input, so this function provides an abstract interface for creating different + kinds of models in a black-box way. You need to pass in a TensorFlow node as + the 'fingerprint' input, and this should output a batch of 1D features that + describe the audio. Typically this will be derived from a spectrogram that's + been run through an MFCC, but in theory it can be any feature vector of the + size specified in model_settings['fingerprint_size']. + + The function will build the graph it needs in the current TensorFlow graph, + and return the tensorflow output that will contain the 'logits' input to the + softmax prediction process. If training flag is on, it will also return a + placeholder node that can be used to control the dropout amount. + + See the implementations below for the possible model architectures that can be + requested. + + Args: + fingerprint_input: TensorFlow node that will output audio feature vectors. + model_settings: Dictionary of information about the model. + model_architecture: String specifying which kind of model to create. + is_training: Whether the model is going to be used for training. + runtime_settings: Dictionary of information about the runtime. + + Returns: + TensorFlow node outputting logits results, and optionally a dropout + placeholder. + + Raises: + Exception: If the architecture type isn't recognized. + """ + if model_architecture == 'single_fc': + return create_single_fc_model(fingerprint_input, model_settings, + is_training) + elif model_architecture == 'conv': + return create_conv_model(fingerprint_input, model_settings, is_training) + elif model_architecture == 'low_latency_conv': + return create_low_latency_conv_model(fingerprint_input, model_settings, + is_training) + elif model_architecture == 'low_latency_svdf': + return create_low_latency_svdf_model(fingerprint_input, model_settings, + is_training, runtime_settings) + elif model_architecture == 'dnn': + return create_dnn_model(fingerprint_input, model_settings, model_size_info, + is_training) + elif model_architecture == 'cnn': + return create_cnn_model(fingerprint_input, model_settings, model_size_info, + is_training) + elif model_architecture == 'basic_lstm': + return create_basic_lstm_model(fingerprint_input, model_settings, + model_size_info, is_training) + elif model_architecture == 'lstm': + return create_lstm_model(fingerprint_input, model_settings, + model_size_info, is_training) + elif model_architecture == 'gru': + return create_gru_model(fingerprint_input, model_settings, model_size_info, + is_training) + elif model_architecture == 'crnn': + return create_crnn_model(fingerprint_input, model_settings, model_size_info, + is_training) + elif model_architecture == 'ds_cnn': + return create_ds_cnn_model(fingerprint_input, model_settings, + model_size_info, is_training) + else: + raise Exception('model_architecture argument "' + model_architecture + + '" not recognized, should be one of "single_fc", "conv",' + + ' "low_latency_conv", "low_latency_svdf",'+ + ' "dnn", "cnn", "basic_lstm", "lstm",'+ + ' "gru", "crnn" or "ds_cnn"') + + +def load_variables_from_checkpoint(sess, start_checkpoint): + """Utility function to centralize checkpoint restoration. + + Args: + sess: TensorFlow session. + start_checkpoint: Path to saved checkpoint on disk. + """ + saver = tf.train.Saver(tf.global_variables()) + saver.restore(sess, start_checkpoint) + + +def create_single_fc_model(fingerprint_input, model_settings, is_training): + """Builds a model with a single hidden fully-connected layer. + + This is a very simple model with just one matmul and bias layer. As you'd + expect, it doesn't produce very accurate results, but it is very fast and + simple, so it's useful for sanity testing. + + Here's the layout of the graph: + + (fingerprint_input) + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + + Args: + fingerprint_input: TensorFlow node that will output audio feature vectors. + model_settings: Dictionary of information about the model. + is_training: Whether the model is going to be used for training. + + Returns: + TensorFlow node outputting logits results, and optionally a dropout + placeholder. + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + fingerprint_size = model_settings['fingerprint_size'] + label_count = model_settings['label_count'] + weights = tf.Variable( + tf.truncated_normal([fingerprint_size, label_count], stddev=0.001)) + bias = tf.Variable(tf.zeros([label_count])) + logits = tf.matmul(fingerprint_input, weights) + bias + if is_training: + return logits, dropout_prob + else: + return logits + + +def create_conv_model(fingerprint_input, model_settings, is_training): + """Builds a standard convolutional model. + + This is roughly the network labeled as 'cnn-trad-fpool3' in the + 'Convolutional Neural Networks for Small-footprint Keyword Spotting' paper: + http://www.isca-speech.org/archive/interspeech_2015/papers/i15_1478.pdf + + Here's the layout of the graph: + + (fingerprint_input) + v + [Conv2D]<-(weights) + v + [BiasAdd]<-(bias) + v + [Relu] + v + [MaxPool] + v + [Conv2D]<-(weights) + v + [BiasAdd]<-(bias) + v + [Relu] + v + [MaxPool] + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + + This produces fairly good quality results, but can involve a large number of + weight parameters and computations. For a cheaper alternative from the same + paper with slightly less accuracy, see 'low_latency_conv' below. + + During training, dropout nodes are introduced after each relu, controlled by a + placeholder. + + Args: + fingerprint_input: TensorFlow node that will output audio feature vectors. + model_settings: Dictionary of information about the model. + is_training: Whether the model is going to be used for training. + + Returns: + TensorFlow node outputting logits results, and optionally a dropout + placeholder. + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size, 1]) + first_filter_width = 8 + first_filter_height = 20 + first_filter_count = 64 + first_weights = tf.Variable( + tf.truncated_normal( + [first_filter_height, first_filter_width, 1, first_filter_count], + stddev=0.01)) + first_bias = tf.Variable(tf.zeros([first_filter_count])) + first_conv = tf.nn.conv2d(fingerprint_4d, first_weights, [1, 1, 1, 1], + 'SAME') + first_bias + first_relu = tf.nn.relu(first_conv) + if is_training: + first_dropout = npu_ops.dropout(first_relu, dropout_prob) + else: + first_dropout = first_relu + max_pool = tf.nn.max_pool(first_dropout, [1, 2, 2, 1], [1, 2, 2, 1], 'SAME') + second_filter_width = 4 + second_filter_height = 10 + second_filter_count = 64 + second_weights = tf.Variable( + tf.truncated_normal( + [ + second_filter_height, second_filter_width, first_filter_count, + second_filter_count + ], + stddev=0.01)) + second_bias = tf.Variable(tf.zeros([second_filter_count])) + second_conv = tf.nn.conv2d(max_pool, second_weights, [1, 1, 1, 1], + 'SAME') + second_bias + second_relu = tf.nn.relu(second_conv) + if is_training: + second_dropout = npu_ops.dropout(second_relu, dropout_prob) + else: + second_dropout = second_relu + second_conv_shape = second_dropout.get_shape() + second_conv_output_width = second_conv_shape[2] + second_conv_output_height = second_conv_shape[1] + second_conv_element_count = int( + second_conv_output_width * second_conv_output_height * + second_filter_count) + flattened_second_conv = tf.reshape(second_dropout, + [-1, second_conv_element_count]) + label_count = model_settings['label_count'] + final_fc_weights = tf.Variable( + tf.truncated_normal( + [second_conv_element_count, label_count], stddev=0.01)) + final_fc_bias = tf.Variable(tf.zeros([label_count])) + final_fc = tf.matmul(flattened_second_conv, final_fc_weights) + final_fc_bias + if is_training: + return final_fc, dropout_prob + else: + return final_fc + + +def create_low_latency_conv_model(fingerprint_input, model_settings, + is_training): + """Builds a convolutional model with low compute requirements. + + This is roughly the network labeled as 'cnn-one-fstride4' in the + 'Convolutional Neural Networks for Small-footprint Keyword Spotting' paper: + http://www.isca-speech.org/archive/interspeech_2015/papers/i15_1478.pdf + + Here's the layout of the graph: + + (fingerprint_input) + v + [Conv2D]<-(weights) + v + [BiasAdd]<-(bias) + v + [Relu] + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + + This produces slightly lower quality results than the 'conv' model, but needs + fewer weight parameters and computations. + + During training, dropout nodes are introduced after the relu, controlled by a + placeholder. + + Args: + fingerprint_input: TensorFlow node that will output audio feature vectors. + model_settings: Dictionary of information about the model. + is_training: Whether the model is going to be used for training. + + Returns: + TensorFlow node outputting logits results, and optionally a dropout + placeholder. + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size, 1]) + first_filter_width = 8 + first_filter_height = input_time_size + first_filter_count = 186 + first_filter_stride_x = 1 + first_filter_stride_y = 1 + first_weights = tf.Variable( + tf.truncated_normal( + [first_filter_height, first_filter_width, 1, first_filter_count], + stddev=0.01)) + first_bias = tf.Variable(tf.zeros([first_filter_count])) + first_conv = tf.nn.conv2d(fingerprint_4d, first_weights, [ + 1, first_filter_stride_y, first_filter_stride_x, 1 + ], 'VALID') + first_bias + first_relu = tf.nn.relu(first_conv) + if is_training: + first_dropout = npu_ops.dropout(first_relu, dropout_prob) + else: + first_dropout = first_relu + first_conv_output_width = math.floor( + (input_frequency_size - first_filter_width + first_filter_stride_x) / + first_filter_stride_x) + first_conv_output_height = math.floor( + (input_time_size - first_filter_height + first_filter_stride_y) / + first_filter_stride_y) + first_conv_element_count = int( + first_conv_output_width * first_conv_output_height * first_filter_count) + flattened_first_conv = tf.reshape(first_dropout, + [-1, first_conv_element_count]) + first_fc_output_channels = 128 + first_fc_weights = tf.Variable( + tf.truncated_normal( + [first_conv_element_count, first_fc_output_channels], stddev=0.01)) + first_fc_bias = tf.Variable(tf.zeros([first_fc_output_channels])) + first_fc = tf.matmul(flattened_first_conv, first_fc_weights) + first_fc_bias + if is_training: + second_fc_input = npu_ops.dropout(first_fc, dropout_prob) + else: + second_fc_input = first_fc + second_fc_output_channels = 128 + second_fc_weights = tf.Variable( + tf.truncated_normal( + [first_fc_output_channels, second_fc_output_channels], stddev=0.01)) + second_fc_bias = tf.Variable(tf.zeros([second_fc_output_channels])) + second_fc = tf.matmul(second_fc_input, second_fc_weights) + second_fc_bias + if is_training: + final_fc_input = npu_ops.dropout(second_fc, dropout_prob) + else: + final_fc_input = second_fc + label_count = model_settings['label_count'] + final_fc_weights = tf.Variable( + tf.truncated_normal( + [second_fc_output_channels, label_count], stddev=0.01)) + final_fc_bias = tf.Variable(tf.zeros([label_count])) + final_fc = tf.matmul(final_fc_input, final_fc_weights) + final_fc_bias + if is_training: + return final_fc, dropout_prob + else: + return final_fc + + +def create_low_latency_svdf_model(fingerprint_input, model_settings, + is_training, runtime_settings): + """Builds an SVDF model with low compute requirements. + + This is based in the topology presented in the 'Compressing Deep Neural + Networks using a Rank-Constrained Topology' paper: + https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43813.pdf + + Here's the layout of the graph: + + (fingerprint_input) + v + [SVDF]<-(weights) + v + [BiasAdd]<-(bias) + v + [Relu] + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + [MatMul]<-(weights) + v + [BiasAdd]<-(bias) + v + + This model produces lower recognition accuracy than the 'conv' model above, + but requires fewer weight parameters and, significantly fewer computations. + + During training, dropout nodes are introduced after the relu, controlled by a + placeholder. + + Args: + fingerprint_input: TensorFlow node that will output audio feature vectors. + The node is expected to produce a 2D Tensor of shape: + [batch, model_settings['dct_coefficient_count'] * + model_settings['spectrogram_length']] + with the features corresponding to the same time slot arranged contiguously, + and the oldest slot at index [:, 0], and newest at [:, -1]. + model_settings: Dictionary of information about the model. + is_training: Whether the model is going to be used for training. + runtime_settings: Dictionary of information about the runtime. + + Returns: + TensorFlow node outputting logits results, and optionally a dropout + placeholder. + + Raises: + ValueError: If the inputs tensor is incorrectly shaped. + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + + # Validation. + input_shape = fingerprint_input.get_shape() + if len(input_shape) != 2: + raise ValueError('Inputs to `SVDF` should have rank == 2.') + if input_shape[-1].value is None: + raise ValueError('The last dimension of the inputs to `SVDF` ' + 'should be defined. Found `None`.') + if input_shape[-1].value % input_frequency_size != 0: + raise ValueError('Inputs feature dimension %d must be a multiple of ' + 'frame size %d', fingerprint_input.shape[-1].value, + input_frequency_size) + + # Set number of units (i.e. nodes) and rank. + rank = 2 + num_units = 1280 + # Number of filters: pairs of feature and time filters. + num_filters = rank * num_units + # Create the runtime memory: [num_filters, batch, input_time_size] + batch = 1 + memory = tf.Variable(tf.zeros([num_filters, batch, input_time_size]), + trainable=False, name='runtime-memory') + # Determine the number of new frames in the input, such that we only operate + # on those. For training we do not use the memory, and thus use all frames + # provided in the input. + # new_fingerprint_input: [batch, num_new_frames*input_frequency_size] + if is_training: + num_new_frames = input_time_size + else: + window_stride_ms = int(model_settings['window_stride_samples'] * 1000 / + model_settings['sample_rate']) + num_new_frames = tf.cond( + tf.equal(tf.count_nonzero(memory), 0), + lambda: input_time_size, + lambda: int(runtime_settings['clip_stride_ms'] / window_stride_ms)) + new_fingerprint_input = fingerprint_input[ + :, -num_new_frames*input_frequency_size:] + # Expand to add input channels dimension. + new_fingerprint_input = tf.expand_dims(new_fingerprint_input, 2) + + # Create the frequency filters. + weights_frequency = tf.Variable( + tf.truncated_normal([input_frequency_size, num_filters], stddev=0.01)) + # Expand to add input channels dimensions. + # weights_frequency: [input_frequency_size, 1, num_filters] + weights_frequency = tf.expand_dims(weights_frequency, 1) + # Convolve the 1D feature filters sliding over the time dimension. + # activations_time: [batch, num_new_frames, num_filters] + activations_time = tf.nn.conv1d( + new_fingerprint_input, weights_frequency, input_frequency_size, 'VALID') + # Rearrange such that we can perform the batched matmul. + # activations_time: [num_filters, batch, num_new_frames] + activations_time = tf.transpose(activations_time, perm=[2, 0, 1]) + + # Runtime memory optimization. + if not is_training: + # We need to drop the activations corresponding to the oldest frames, and + # then add those corresponding to the new frames. + new_memory = memory[:, :, num_new_frames:] + new_memory = tf.concat([new_memory, activations_time], 2) + tf.assign(memory, new_memory) + activations_time = new_memory + + # Create the time filters. + weights_time = tf.Variable( + tf.truncated_normal([num_filters, input_time_size], stddev=0.01)) + # Apply the time filter on the outputs of the feature filters. + # weights_time: [num_filters, input_time_size, 1] + # outputs: [num_filters, batch, 1] + weights_time = tf.expand_dims(weights_time, 2) + outputs = tf.matmul(activations_time, weights_time) + # Split num_units and rank into separate dimensions (the remaining + # dimension is the input_shape[0] -i.e. batch size). This also squeezes + # the last dimension, since it's not used. + # [num_filters, batch, 1] => [num_units, rank, batch] + outputs = tf.reshape(outputs, [num_units, rank, -1]) + # Sum the rank outputs per unit => [num_units, batch]. + units_output = tf.reduce_sum(outputs, axis=1) + # Transpose to shape [batch, num_units] + units_output = tf.transpose(units_output) + + # Appy bias. + bias = tf.Variable(tf.zeros([num_units])) + first_bias = tf.nn.bias_add(units_output, bias) + + # Relu. + first_relu = tf.nn.relu(first_bias) + + if is_training: + first_dropout = npu_ops.dropout(first_relu, dropout_prob) + else: + first_dropout = first_relu + + first_fc_output_channels = 256 + first_fc_weights = tf.Variable( + tf.truncated_normal([num_units, first_fc_output_channels], stddev=0.01)) + first_fc_bias = tf.Variable(tf.zeros([first_fc_output_channels])) + first_fc = tf.matmul(first_dropout, first_fc_weights) + first_fc_bias + if is_training: + second_fc_input = npu_ops.dropout(first_fc, dropout_prob) + else: + second_fc_input = first_fc + second_fc_output_channels = 256 + second_fc_weights = tf.Variable( + tf.truncated_normal( + [first_fc_output_channels, second_fc_output_channels], stddev=0.01)) + second_fc_bias = tf.Variable(tf.zeros([second_fc_output_channels])) + second_fc = tf.matmul(second_fc_input, second_fc_weights) + second_fc_bias + if is_training: + final_fc_input = npu_ops.dropout(second_fc, dropout_prob) + else: + final_fc_input = second_fc + label_count = model_settings['label_count'] + final_fc_weights = tf.Variable( + tf.truncated_normal( + [second_fc_output_channels, label_count], stddev=0.01)) + final_fc_bias = tf.Variable(tf.zeros([label_count])) + final_fc = tf.matmul(final_fc_input, final_fc_weights) + final_fc_bias + if is_training: + return final_fc, dropout_prob + else: + return final_fc + +def create_dnn_model(fingerprint_input, model_settings, model_size_info, + is_training): + """Builds a model with multiple hidden fully-connected layers. + model_size_info: length of the array defines the number of hidden-layers and + each element in the array represent the number of neurons + in that layer + """ + + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + fingerprint_size = model_settings['fingerprint_size'] + label_count = model_settings['label_count'] + num_layers = len(model_size_info) + layer_dim = [fingerprint_size] + layer_dim.extend(model_size_info) + flow = fingerprint_input + tf.summary.histogram('input', flow) + for i in range(1, num_layers + 1): + with tf.variable_scope('fc'+str(i)): + W = tf.get_variable('W', shape=[layer_dim[i-1], layer_dim[i]], + initializer=tf.contrib.layers.xavier_initializer()) + tf.summary.histogram('fc_'+str(i)+'_w', W) + b = tf.get_variable('b', shape=[layer_dim[i]]) + tf.summary.histogram('fc_'+str(i)+'_b', b) + flow = tf.matmul(flow, W) + b + flow = tf.nn.relu(flow) + if is_training: + flow = npu_ops.dropout(flow, dropout_prob) + + weights = tf.get_variable('final_fc', shape=[layer_dim[-1], label_count], + initializer=tf.contrib.layers.xavier_initializer()) + bias = tf.Variable(tf.zeros([label_count])) + logits = tf.matmul(flow, weights) + bias + if is_training: + return logits, dropout_prob + else: + return logits + +def create_cnn_model(fingerprint_input, model_settings, model_size_info, + is_training): + """Builds a model with 2 convolution layers followed by a linear layer and + a hidden fully-connected layer. + model_size_info: defines the first and second convolution parameters in + {number of conv features, conv filter height, width, stride in y,x dir.}, + followed by linear layer size and fully-connected layer size. + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size, 1]) + + first_filter_count = model_size_info[0] + first_filter_height = model_size_info[1] #time axis + first_filter_width = model_size_info[2] #frequency axis + first_filter_stride_y = model_size_info[3] #time axis + first_filter_stride_x = model_size_info[4] #frequency_axis + + second_filter_count = model_size_info[5] + second_filter_height = model_size_info[6] #time axis + second_filter_width = model_size_info[7] #frequency axis + second_filter_stride_y = model_size_info[8] #time axis + second_filter_stride_x = model_size_info[9] #frequency_axis + + linear_layer_size = model_size_info[10] + fc_size = model_size_info[11] + + # first conv + first_weights = tf.Variable( + tf.truncated_normal( + [first_filter_height, first_filter_width, 1, first_filter_count], + stddev=0.01)) + first_bias = tf.Variable(tf.zeros([first_filter_count])) + first_conv = tf.nn.conv2d(fingerprint_4d, first_weights, [ + 1, first_filter_stride_y, first_filter_stride_x, 1 + ], 'VALID') + first_bias + first_conv = tf.layers.batch_normalization(first_conv, training=is_training, + name='bn1') + first_relu = tf.nn.relu(first_conv) + if is_training: + first_dropout = npu_ops.dropout(first_relu, dropout_prob) + else: + first_dropout = first_relu + first_conv_output_width = math.ceil( + (input_frequency_size - first_filter_width + 1) / + first_filter_stride_x) + first_conv_output_height = math.ceil( + (input_time_size - first_filter_height + 1) / + first_filter_stride_y) + + # second conv + second_weights = tf.Variable( + tf.truncated_normal( + [second_filter_height, second_filter_width, first_filter_count, + second_filter_count], + stddev=0.01)) + second_bias = tf.Variable(tf.zeros([second_filter_count])) + second_conv = tf.nn.conv2d(first_dropout, second_weights, [ + 1, second_filter_stride_y, second_filter_stride_x, 1 + ], 'VALID') + second_bias + second_conv = tf.layers.batch_normalization(second_conv, training=is_training, + name='bn2') + second_relu = tf.nn.relu(second_conv) + if is_training: + second_dropout = npu_ops.dropout(second_relu, dropout_prob) + else: + second_dropout = second_relu + second_conv_output_width = math.ceil( + (first_conv_output_width - second_filter_width + 1) / + second_filter_stride_x) + second_conv_output_height = math.ceil( + (first_conv_output_height - second_filter_height + 1) / + second_filter_stride_y) + + second_conv_element_count = int( + second_conv_output_width*second_conv_output_height*second_filter_count) + flattened_second_conv = tf.reshape(second_dropout, + [-1, second_conv_element_count]) + + # linear layer + W = tf.get_variable('W', shape=[second_conv_element_count, linear_layer_size], + initializer=tf.contrib.layers.xavier_initializer()) + b = tf.get_variable('b', shape=[linear_layer_size]) + flow = tf.matmul(flattened_second_conv, W) + b + + # first fc + first_fc_output_channels = fc_size + first_fc_weights = tf.Variable( + tf.truncated_normal( + [linear_layer_size, first_fc_output_channels], stddev=0.01)) + first_fc_bias = tf.Variable(tf.zeros([first_fc_output_channels])) + first_fc = tf.matmul(flow, first_fc_weights) + first_fc_bias + first_fc = tf.layers.batch_normalization(first_fc, training=is_training, + name='bn3') + first_fc = tf.nn.relu(first_fc) + if is_training: + final_fc_input = npu_ops.dropout(first_fc, dropout_prob) + else: + final_fc_input = first_fc + label_count = model_settings['label_count'] + final_fc_weights = tf.Variable( + tf.truncated_normal( + [first_fc_output_channels, label_count], stddev=0.01)) + final_fc_bias = tf.Variable(tf.zeros([label_count])) + final_fc = tf.matmul(final_fc_input, final_fc_weights) + final_fc_bias + if is_training: + return final_fc, dropout_prob + else: + return final_fc + + +def create_basic_lstm_model(fingerprint_input, model_settings, model_size_info, + is_training): + """Builds a model with a basic lstm layer (without output projection and + peep-hole connections) + model_size_info: defines the number of memory cells in basic lstm model + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size]) + + num_classes = model_settings['label_count'] + + if type(model_size_info) is list: + LSTM_units = model_size_info[0] + else: + LSTM_units = model_size_info + + with tf.name_scope('LSTM-Layer'): + with tf.variable_scope("lstm"): + lstmcell = tf.contrib.rnn.BasicLSTMCell(LSTM_units, forget_bias=1.0, + state_is_tuple=True) + _, last = tf.nn.dynamic_rnn(cell=lstmcell, inputs=fingerprint_4d, + dtype=tf.float32) + flow = last[-1] + + with tf.name_scope('Output-Layer'): + W_o = tf.get_variable('W_o', shape=[LSTM_units, num_classes], + initializer=tf.contrib.layers.xavier_initializer()) + b_o = tf.get_variable('b_o', shape=[num_classes]) + logits = tf.matmul(flow, W_o) + b_o + + if is_training: + return logits, dropout_prob + else: + return logits + +def create_lstm_model(fingerprint_input, model_settings, model_size_info, + is_training): + """Builds a model with a lstm layer (with output projection layer and + peep-hole connections) + Based on model described in https://arxiv.org/abs/1705.02411 + model_size_info: [projection size, memory cells in LSTM] + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size]) + + num_classes = model_settings['label_count'] + projection_units = model_size_info[0] + LSTM_units = model_size_info[1] + with tf.name_scope('LSTM-Layer'): + with tf.variable_scope("lstm"): + lstmcell = tf.contrib.rnn.LSTMCell(LSTM_units, use_peepholes=True, + num_proj=projection_units) + _, last = tf.nn.dynamic_rnn(cell=lstmcell, inputs=fingerprint_4d, + dtype=tf.float32) + flow = last[-1] + + with tf.name_scope('Output-Layer'): + W_o = tf.get_variable('W_o', shape=[projection_units, num_classes], + initializer=tf.contrib.layers.xavier_initializer()) + b_o = tf.get_variable('b_o', shape=[num_classes]) + logits = tf.matmul(flow, W_o) + b_o + + if is_training: + return logits, dropout_prob + else: + return logits + +class LayerNormGRUCell(rnn_cell_impl.RNNCell): + + def __init__(self, num_units, forget_bias=1.0, + input_size=None, activation=math_ops.tanh, + layer_norm=True, norm_gain=1.0, norm_shift=0.0, + dropout_keep_prob=1.0, dropout_prob_seed=None, + reuse=None): + + super(LayerNormGRUCell, self).__init__(_reuse=reuse) + + if input_size is not None: + tf.logging.info("%s: The input_size parameter is deprecated.", self) + + self._num_units = num_units + self._activation = activation + self._forget_bias = forget_bias + self._keep_prob = dropout_keep_prob + self._seed = dropout_prob_seed + self._layer_norm = layer_norm + self._g = norm_gain + self._b = norm_shift + self._reuse = reuse + + @property + def state_size(self): + return self._num_units + + @property + def output_size(self): + return self._num_units + + def _norm(self, inp, scope): + shape = inp.get_shape()[-1:] + gamma_init = init_ops.constant_initializer(self._g) + beta_init = init_ops.constant_initializer(self._b) + with vs.variable_scope(scope): + # Initialize beta and gamma for use by layer_norm. + vs.get_variable("gamma", shape=shape, initializer=gamma_init) + vs.get_variable("beta", shape=shape, initializer=beta_init) + normalized = layers.layer_norm(inp, reuse=True, scope=scope) + return normalized + + def _linear(self, args, copy): + out_size = copy * self._num_units + proj_size = args.get_shape()[-1] + weights = vs.get_variable("kernel", [proj_size, out_size]) + out = math_ops.matmul(args, weights) + if not self._layer_norm: + bias = vs.get_variable("bias", [out_size]) + out = nn_ops.bias_add(out, bias) + return out + + def call(self, inputs, state): + """LSTM cell with layer normalization and recurrent dropout.""" + with vs.variable_scope("gates"): + h = state + args = array_ops.concat([inputs, h], 1) + concat = self._linear(args, 2) + + z, r = array_ops.split(value=concat, num_or_size_splits=2, axis=1) + if self._layer_norm: + z = self._norm(z, "update") + r = self._norm(r, "reset") + + with vs.variable_scope("candidate"): + args = array_ops.concat([inputs, math_ops.sigmoid(r) * h], 1) + new_c = self._linear(args, 1) + if self._layer_norm: + new_c = self._norm(new_c, "state") + new_h = self._activation(new_c) * math_ops.sigmoid(z) + \ + (1 - math_ops.sigmoid(z)) * h + return new_h, new_h + +def create_gru_model(fingerprint_input, model_settings, model_size_info, + is_training): + """Builds a model with multi-layer GRUs + model_size_info: [number of GRU layers, number of GRU cells per layer] + Optionally, the bi-directional GRUs and/or GRU with layer-normalization + can be explored. + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size]) + + num_classes = model_settings['label_count'] + + layer_norm = False + bidirectional = False + + num_layers = model_size_info[0] + gru_units = model_size_info[1] + + gru_cell_fw = [] + gru_cell_bw = [] + if layer_norm: + for i in range(num_layers): + gru_cell_fw.append(LayerNormGRUCell(gru_units)) + if bidirectional: + gru_cell_bw.append(LayerNormGRUCell(gru_units)) + else: + for i in range(num_layers): + gru_cell_fw.append(tf.contrib.rnn.GRUCell(gru_units)) + if bidirectional: + gru_cell_bw.append(tf.contrib.rnn.GRUCell(gru_units)) + + if bidirectional: + outputs, output_state_fw, output_state_bw = \ + tf.contrib.rnn.stack_bidirectional_dynamic_rnn(gru_cell_fw, gru_cell_bw, + fingerprint_4d, dtype=tf.float32) + flow = outputs[:, -1, :] + else: + cells = tf.contrib.rnn.MultiRNNCell(gru_cell_fw) + _, last = tf.nn.dynamic_rnn(cell=cells, inputs=fingerprint_4d, + dtype=tf.float32) + flow = last[-1] + + with tf.name_scope('Output-Layer'): + W_o = tf.get_variable('W_o', shape=[flow.get_shape()[-1], num_classes], + initializer=tf.contrib.layers.xavier_initializer()) + b_o = tf.get_variable('b_o', shape=[num_classes]) + logits = tf.matmul(flow, W_o) + b_o + + if is_training: + return logits, dropout_prob + else: + return logits + + +def create_crnn_model(fingerprint_input, model_settings, + model_size_info, is_training): + """Builds a model with convolutional recurrent networks with GRUs + Based on the model definition in https://arxiv.org/abs/1703.05390 + model_size_info: defines the following convolution layer parameters + {number of conv features, conv filter height, width, stride in y,x dir.}, + followed by number of GRU layers and number of GRU cells per layer + Optionally, the bi-directional GRUs and/or GRU with layer-normalization + can be explored. + """ + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size, 1]) + + layer_norm = False + bidirectional = False + + # CNN part + first_filter_count = model_size_info[0] + first_filter_height = model_size_info[1] + first_filter_width = model_size_info[2] + first_filter_stride_y = model_size_info[3] + first_filter_stride_x = model_size_info[4] + + first_weights = tf.get_variable('W', shape=[first_filter_height, + first_filter_width, 1, first_filter_count], + initializer=tf.contrib.layers.xavier_initializer()) + + first_bias = tf.Variable(tf.zeros([first_filter_count])) + first_conv = tf.nn.conv2d(fingerprint_4d, first_weights, [ + 1, first_filter_stride_y, first_filter_stride_x, 1 + ], 'VALID') + first_bias + first_relu = tf.nn.relu(first_conv) + if is_training: + first_dropout = npu_ops.dropout(first_relu, dropout_prob) + else: + first_dropout = first_relu + first_conv_output_width = int(math.floor( + (input_frequency_size - first_filter_width + first_filter_stride_x) / + first_filter_stride_x)) + first_conv_output_height = int(math.floor( + (input_time_size - first_filter_height + first_filter_stride_y) / + first_filter_stride_y)) + + # GRU part + num_rnn_layers = model_size_info[5] + RNN_units = model_size_info[6] + flow = tf.reshape(first_dropout, [-1, first_conv_output_height, + first_conv_output_width * first_filter_count]) + cell_fw = [] + cell_bw = [] + if layer_norm: + for i in range(num_rnn_layers): + cell_fw.append(LayerNormGRUCell(RNN_units)) + if bidirectional: + cell_bw.append(LayerNormGRUCell(RNN_units)) + else: + for i in range(num_rnn_layers): + cell_fw.append(tf.contrib.rnn.GRUCell(RNN_units)) + if bidirectional: + cell_bw.append(tf.contrib.rnn.GRUCell(RNN_units)) + + if bidirectional: + outputs, output_state_fw, output_state_bw = \ + tf.contrib.rnn.stack_bidirectional_dynamic_rnn(cell_fw, cell_bw, flow, + dtype=tf.float32) + flow_dim = first_conv_output_height*RNN_units*2 + flow = tf.reshape(outputs, [-1, flow_dim]) + else: + cells = tf.contrib.rnn.MultiRNNCell(cell_fw) + _, last = tf.nn.dynamic_rnn(cell=cells, inputs=flow, dtype=tf.float32) + flow_dim = RNN_units + flow = last[-1] + + first_fc_output_channels = model_size_info[7] + + first_fc_weights = tf.get_variable('fcw', shape=[flow_dim, + first_fc_output_channels], + initializer=tf.contrib.layers.xavier_initializer()) + + first_fc_bias = tf.Variable(tf.zeros([first_fc_output_channels])) + first_fc = tf.nn.relu(tf.matmul(flow, first_fc_weights) + first_fc_bias) + if is_training: + final_fc_input = npu_ops.dropout(first_fc, dropout_prob) + else: + final_fc_input = first_fc + + label_count = model_settings['label_count'] + + final_fc_weights = tf.Variable( + tf.truncated_normal( + [first_fc_output_channels, label_count], stddev=0.01)) + + final_fc_bias = tf.Variable(tf.zeros([label_count])) + final_fc = tf.matmul(final_fc_input, final_fc_weights) + final_fc_bias + if is_training: + return final_fc, dropout_prob + else: + return final_fc + +def create_ds_cnn_model(fingerprint_input, model_settings, model_size_info, + is_training): + """Builds a model with depthwise separable convolutional neural network + Model definition is based on https://arxiv.org/abs/1704.04861 and + Tensorflow implementation: https://github.com/Zehaos/MobileNet + + model_size_info: defines number of layers, followed by the DS-Conv layer + parameters in the order {number of conv features, conv filter height, + width and stride in y,x dir.} for each of the layers. + Note that first layer is always regular convolution, but the remaining + layers are all depthwise separable convolutions. + """ + + def ds_cnn_arg_scope(weight_decay=0): + """Defines the default ds_cnn argument scope. + Args: + weight_decay: The weight decay to use for regularizing the model. + Returns: + An `arg_scope` to use for the DS-CNN model. + """ + with slim.arg_scope( + [slim.convolution2d, slim.separable_convolution2d], + weights_initializer=slim.initializers.xavier_initializer(), + biases_initializer=slim.init_ops.zeros_initializer(), + weights_regularizer=slim.l2_regularizer(weight_decay)) as sc: + return sc + + def _depthwise_separable_conv(inputs, + num_pwc_filters, + sc, + kernel_size, + stride): + """ Helper function to build the depth-wise separable convolution layer. + """ + + # skip pointwise by setting num_outputs=None + depthwise_conv = slim.separable_convolution2d(inputs, + num_outputs=None, + stride=stride, + depth_multiplier=1, + kernel_size=kernel_size, + scope=sc+'/dw_conv') + + bn = slim.batch_norm(depthwise_conv, scope=sc+'/dw_conv/batch_norm') + pointwise_conv = slim.convolution2d(bn, + num_pwc_filters, + kernel_size=[1, 1], + scope=sc+'/pw_conv') + bn = slim.batch_norm(pointwise_conv, scope=sc+'/pw_conv/batch_norm') + return bn + + + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + + label_count = model_settings['label_count'] + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size, 1]) + + t_dim = input_time_size + f_dim = input_frequency_size + + #Extract model dimensions from model_size_info + num_layers = model_size_info[0] + conv_feat = [None]*num_layers + conv_kt = [None]*num_layers + conv_kf = [None]*num_layers + conv_st = [None]*num_layers + conv_sf = [None]*num_layers + i=1 + for layer_no in range(0,num_layers): + conv_feat[layer_no] = model_size_info[i] + i += 1 + conv_kt[layer_no] = model_size_info[i] + i += 1 + conv_kf[layer_no] = model_size_info[i] + i += 1 + conv_st[layer_no] = model_size_info[i] + i += 1 + conv_sf[layer_no] = model_size_info[i] + i += 1 + + scope = 'DS-CNN' + with tf.variable_scope(scope) as sc: + end_points_collection = sc.name + '_end_points' + with slim.arg_scope([slim.convolution2d, slim.separable_convolution2d], + activation_fn=None, + weights_initializer=slim.initializers.xavier_initializer(), + biases_initializer=slim.init_ops.zeros_initializer(), + outputs_collections=[end_points_collection]): + with slim.arg_scope([slim.batch_norm], + is_training=is_training, + decay=0.96, + updates_collections=None, + activation_fn=tf.nn.relu): + for layer_no in range(0,num_layers): + if layer_no==0: + net = slim.convolution2d(fingerprint_4d, conv_feat[layer_no],\ + [conv_kt[layer_no], conv_kf[layer_no]], stride=[conv_st[layer_no], conv_sf[layer_no]], padding='SAME', scope='conv_1') + net = slim.batch_norm(net, scope='conv_1/batch_norm') + else: + net = _depthwise_separable_conv(net, conv_feat[layer_no], \ + kernel_size = [conv_kt[layer_no],conv_kf[layer_no]], \ + stride = [conv_st[layer_no],conv_sf[layer_no]], sc='conv_ds_'+str(layer_no)) + t_dim = math.ceil(t_dim/float(conv_st[layer_no])) + f_dim = math.ceil(f_dim/float(conv_sf[layer_no])) + + net = slim.avg_pool2d(net, [t_dim, f_dim], scope='avg_pool') + + net = tf.squeeze(net, [1, 2], name='SpatialSqueeze') + logits = slim.fully_connected(net, label_count, activation_fn=None, scope='fc1') + + if is_training: + return logits, dropout_prob + else: + return logits + + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/modelzoo_level.txt b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/modelzoo_level.txt new file mode 100644 index 0000000000000000000000000000000000000000..31529da2e68f25b61e2a3e698a07537281443c03 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/modelzoo_level.txt @@ -0,0 +1,3 @@ +FuncStatus:OK +PerfStatus:OK +PrecisionStatus:OK \ No newline at end of file diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/quant_models.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/quant_models.py new file mode 100644 index 0000000000000000000000000000000000000000..1441929d2abcd7c780eb83723d4a57e02f309cf9 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/quant_models.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017 Arm Inc. All Rights Reserved. +# Added new model definitions for speech command recognition used in +# the paper: https://arxiv.org/pdf/1711.07128.pdf +# Added Quantized model definitions +# + +"""Model definitions for simple speech recognition. + +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import math + +import tensorflow as tf +import tensorflow.contrib.slim as slim +from tensorflow.contrib.layers.python.layers import layers +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import init_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import nn_ops +from tensorflow.python.ops import rnn_cell_impl +from tensorflow.python.ops import variable_scope as vs + +def prepare_model_settings(label_count, sample_rate, clip_duration_ms, + window_size_ms, window_stride_ms, + dct_coefficient_count): + """Calculates common settings needed for all models. + + Args: + label_count: How many classes are to be recognized. + sample_rate: Number of audio samples per second. + clip_duration_ms: Length of each audio clip to be analyzed. + window_size_ms: Duration of frequency analysis window. + window_stride_ms: How far to move in time between frequency windows. + dct_coefficient_count: Number of frequency bins to use for analysis. + + Returns: + Dictionary containing common settings. + """ + desired_samples = int(sample_rate * clip_duration_ms / 1000) + window_size_samples = int(sample_rate * window_size_ms / 1000) + window_stride_samples = int(sample_rate * window_stride_ms / 1000) + length_minus_window = (desired_samples - window_size_samples) + if length_minus_window < 0: + spectrogram_length = 0 + else: + spectrogram_length = 1 + int(length_minus_window / window_stride_samples) + fingerprint_size = dct_coefficient_count * spectrogram_length + return { + 'desired_samples': desired_samples, + 'window_size_samples': window_size_samples, + 'window_stride_samples': window_stride_samples, + 'spectrogram_length': spectrogram_length, + 'dct_coefficient_count': dct_coefficient_count, + 'fingerprint_size': fingerprint_size, + 'label_count': label_count, + 'sample_rate': sample_rate, + } + + +def create_model(fingerprint_input, model_settings, model_architecture, + model_size_info, act_max, is_training, \ + runtime_settings=None): + """Builds a model of the requested architecture compatible with the settings. + + There are many possible ways of deriving predictions from a spectrogram + input, so this function provides an abstract interface for creating different + kinds of models in a black-box way. You need to pass in a TensorFlow node as + the 'fingerprint' input, and this should output a batch of 1D features that + describe the audio. Typically this will be derived from a spectrogram that's + been run through an MFCC, but in theory it can be any feature vector of the + size specified in model_settings['fingerprint_size']. + + The function will build the graph it needs in the current TensorFlow graph, + and return the tensorflow output that will contain the 'logits' input to the + softmax prediction process. If training flag is on, it will also return a + placeholder node that can be used to control the dropout amount. + + See the implementations below for the possible model architectures that can be + requested. + + Args: + fingerprint_input: TensorFlow node that will output audio feature vectors. + model_settings: Dictionary of information about the model. + model_architecture: String specifying which kind of model to create. + is_training: Whether the model is going to be used for training. + runtime_settings: Dictionary of information about the runtime. + + Returns: + TensorFlow node outputting logits results, and optionally a dropout + placeholder. + + Raises: + Exception: If the architecture type isn't recognized. + """ + if model_architecture == 'dnn': + return create_dnn_model(fingerprint_input, model_settings, model_size_info, + act_max, is_training) + elif model_architecture == 'ds_cnn': + return create_ds_cnn_model(fingerprint_input, model_settings, + model_size_info, act_max, is_training) + else: + raise Exception('model_architecture argument "' + model_architecture + + '" not recognized, should be one of "single_fc", "conv",' + + ' "low_latency_conv", "low_latency_svdf",'+ + ' "dnn", "cnn", "basic_lstm", "lstm",'+ + ' "gru", "crnn" or "ds_cnn"') + + +def load_variables_from_checkpoint(sess, start_checkpoint): + """Utility function to centralize checkpoint restoration. + + Args: + sess: TensorFlow session. + start_checkpoint: Path to saved checkpoint on disk. + """ + saver = tf.train.Saver(tf.global_variables()) + saver.restore(sess, start_checkpoint) + + +def create_dnn_model(fingerprint_input, model_settings, model_size_info, + act_max, is_training): + """Builds a model with multiple hidden fully-connected layers. + model_size_info: length of the array defines the number of hidden-layers and + each element in the array represent the number of neurons + in that layer + """ + + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + fingerprint_size = model_settings['fingerprint_size'] + label_count = model_settings['label_count'] + num_layers = len(model_size_info) + layer_dim = [fingerprint_size] + layer_dim.extend(model_size_info) + flow = fingerprint_input + if(act_max[0]!=0): + flow = tf.fake_quant_with_min_max_vars(flow, min=-act_max[0], \ + max=act_max[0]-(act_max[0]/128.0), num_bits=8) + for i in range(1, num_layers + 1): + with tf.variable_scope('fc'+str(i)): + W = tf.get_variable('W', shape=[layer_dim[i-1], layer_dim[i]], + initializer=tf.contrib.layers.xavier_initializer()) + b = tf.get_variable('b', shape=[layer_dim[i]]) + flow = tf.matmul(flow, W) + b + if(act_max[i]!=0): + flow = tf.fake_quant_with_min_max_vars(flow, min=-act_max[i], \ + max=act_max[i]-(act_max[i]/128.0), num_bits=8) + flow = tf.nn.relu(flow) + if is_training: + flow = npu_ops.dropout(flow, dropout_prob) + + weights = tf.get_variable('final_fc', shape=[layer_dim[-1], label_count], + initializer=tf.contrib.layers.xavier_initializer()) + bias = tf.Variable(tf.zeros([label_count])) + logits = tf.matmul(flow, weights) + bias + if(act_max[num_layers+1]!=0): + logits = tf.fake_quant_with_min_max_vars(logits, min=-act_max[num_layers+1], \ + max=act_max[num_layers+1]-(act_max[num_layers+1]/128.0), num_bits=8) + if is_training: + return logits, dropout_prob + else: + return logits + +def create_ds_cnn_model(fingerprint_input, model_settings, model_size_info, + act_max, is_training): + """Builds a model with depthwise separable convolutional neural network + Model definition is based on https://arxiv.org/abs/1704.04861 and + Tensorflow implementation: https://github.com/Zehaos/MobileNet + + model_size_info: defines number of layers, followed by the DS-Conv layer + parameters in the order {number of conv features, conv filter height, + width and stride in y,x dir.} for each of the layers. + Note that first layer is always regular convolution, but the remaining + layers are all depthwise separable convolutions. + """ + + def ds_cnn_arg_scope(weight_decay=0): + """Defines the default ds_cnn argument scope. + Args: + weight_decay: The weight decay to use for regularizing the model. + Returns: + An `arg_scope` to use for the DS-CNN model. + """ + with slim.arg_scope( + [slim.convolution2d, slim.separable_convolution2d], + weights_initializer=slim.initializers.xavier_initializer(), + biases_initializer=slim.init_ops.zeros_initializer(), + weights_regularizer=slim.l2_regularizer(weight_decay)) as sc: + return sc + + def _depthwise_separable_conv(inputs, + num_pwc_filters, + sc, + kernel_size, + stride, + layer_no, + act_max): + """ Helper function to build the depth-wise separable convolution layer. + """ + + # skip pointwise by setting num_outputs=None + depthwise_conv = slim.separable_convolution2d(inputs, + num_outputs=None, + stride=stride, + depth_multiplier=1, + kernel_size=kernel_size, + scope=sc+'/dw_conv', + reuse=tf.AUTO_REUSE) + if(act_max[2*layer_no]>0): + depthwise_conv = tf.fake_quant_with_min_max_vars(depthwise_conv, + min=-act_max[2*layer_no], + max=act_max[2*layer_no]-(act_max[2*layer_no]/128.0), + num_bits=8, name='quant_ds_conv'+str(layer_no)) + bn = tf.nn.relu(depthwise_conv) + + # batch-norm weights folded into depthwise conv + # bn = slim.batch_norm(depthwise_conv, scope=sc+'/dw_conv/batch_norm') + pointwise_conv = slim.convolution2d(bn, + num_pwc_filters, + kernel_size=[1, 1], + scope=sc+'/pw_conv', + reuse=tf.AUTO_REUSE) + if(act_max[2*layer_no+1]>0): + pointwise_conv = tf.fake_quant_with_min_max_vars(pointwise_conv, + min=-act_max[2*layer_no+1], + max=act_max[2*layer_no+1]-(act_max[2*layer_no+1]/128.0), + num_bits=8, name='quant_pw_conv'+str(layer_no+1)) + bn = tf.nn.relu(pointwise_conv) + + # batch-norm weights folded into pointwise conv + # bn = slim.batch_norm(pointwise_conv, scope=sc+'/pw_conv/batch_norm') + return bn + + if is_training: + dropout_prob = tf.placeholder(tf.float32, name='dropout_prob') + + label_count = model_settings['label_count'] + input_frequency_size = model_settings['dct_coefficient_count'] + input_time_size = model_settings['spectrogram_length'] + fingerprint_4d = tf.reshape(fingerprint_input, + [-1, input_time_size, input_frequency_size, 1]) + + t_dim = input_time_size + f_dim = input_frequency_size + + #Extract model dimensions from model_size_info + num_layers = model_size_info[0] + conv_feat = [None]*num_layers + conv_kt = [None]*num_layers + conv_kf = [None]*num_layers + conv_st = [None]*num_layers + conv_sf = [None]*num_layers + i=1 + for layer_no in range(0,num_layers): + conv_feat[layer_no] = model_size_info[i] + i += 1 + conv_kt[layer_no] = model_size_info[i] + i += 1 + conv_kf[layer_no] = model_size_info[i] + i += 1 + conv_st[layer_no] = model_size_info[i] + i += 1 + conv_sf[layer_no] = model_size_info[i] + i += 1 + + scope = 'DS-CNN' + with tf.variable_scope(scope) as sc: + end_points_collection = sc.name + '_end_points' + with slim.arg_scope([slim.convolution2d, slim.separable_convolution2d], + activation_fn=None, + weights_initializer=slim.initializers.xavier_initializer(), + biases_initializer=slim.init_ops.zeros_initializer(), + outputs_collections=[end_points_collection]): + with slim.arg_scope([slim.batch_norm], + is_training=is_training, + decay=0.96, + updates_collections=None, + activation_fn=tf.nn.relu): + if act_max[0]>0: + fingerprint_4d = tf.fake_quant_with_min_max_vars(fingerprint_4d, + min=-act_max[0], max=act_max[0]-(act_max[0]/128.0), + num_bits=8, name='quant_input') + for layer_no in range(0,num_layers): + if layer_no==0: + net = slim.convolution2d(fingerprint_4d, conv_feat[layer_no],\ + [conv_kt[layer_no], conv_kf[layer_no]], stride=[conv_st[layer_no], + conv_sf[layer_no]], padding='SAME', scope='conv_1', reuse=tf.AUTO_REUSE) + if act_max[1]>0: + net = tf.fake_quant_with_min_max_vars(net, min=-act_max[1], + max=act_max[1]-(act_max[1]/128.0), num_bits=8, name='quant_conv1') + net = tf.nn.relu(net) + #net = slim.batch_norm(net, scope='conv_1/batch_norm') + else: + net = _depthwise_separable_conv(net, conv_feat[layer_no], \ + kernel_size = [conv_kt[layer_no],conv_kf[layer_no]], \ + stride = [conv_st[layer_no],conv_sf[layer_no]], + sc='conv_ds_'+str(layer_no), + layer_no = layer_no, + act_max = act_max) + t_dim = math.ceil(t_dim/float(conv_st[layer_no])) + f_dim = math.ceil(f_dim/float(conv_sf[layer_no])) + + net = slim.avg_pool2d(net, [t_dim, f_dim], scope='avg_pool') + if act_max[2*num_layers]>0: + net = tf.fake_quant_with_min_max_vars(net, min=-act_max[2*num_layers], + max=act_max[2*num_layers]-(act_max[2*num_layers]/128.0), + num_bits=8, name='quant_pool') + + net = tf.squeeze(net, [1, 2], name='SpatialSqueeze') + logits = slim.fully_connected(net, label_count, activation_fn=None, + scope='fc1', reuse=tf.AUTO_REUSE) + if act_max[2*num_layers+1]>0: + logits = tf.fake_quant_with_min_max_vars(logits, min=-act_max[2*num_layers+1], + max=act_max[2*num_layers+1]-(act_max[2*num_layers+1]/128.0), + num_bits=8, name='quant_fc') + + + if is_training: + return logits, dropout_prob + else: + return logits + + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/quant_test.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/quant_test.py new file mode 100644 index 0000000000000000000000000000000000000000..89d5fcb473f8990e9a6c76c7fd6d674c2e97cb8b --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/quant_test.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017-2018 Arm Inc. All Rights Reserved. +# Adapted from freeze.py to run quantized inference on train/val/test dataset on the +# trained model in the form of checkpoint +# +# + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import argparse +import os.path +import sys +import numpy as np + +import tensorflow as tf +import input_data +import quant_models as models + +def run_quant_inference(wanted_words, sample_rate, clip_duration_ms, + window_size_ms, window_stride_ms, dct_coefficient_count, + model_architecture, model_size_info): + """Creates an audio model with the nodes needed for inference. + + Uses the supplied arguments to create a model, and inserts the input and + output nodes that are needed to use the graph for inference. + + Args: + wanted_words: Comma-separated list of the words we're trying to recognize. + sample_rate: How many samples per second are in the input audio files. + clip_duration_ms: How many samples to analyze for the audio pattern. + window_size_ms: Time slice duration to estimate frequencies from. + window_stride_ms: How far apart time slices should be. + dct_coefficient_count: Number of frequency bands to analyze. + model_architecture: Name of the kind of model to generate. + model_size_info: Model dimensions : different lengths for different models + """ + + tf.logging.set_verbosity(tf.logging.INFO) + sess = tf.InteractiveSession(config=npu_config_proto()) + words_list = input_data.prepare_words_list(wanted_words.split(',')) + model_settings = models.prepare_model_settings( + len(words_list), sample_rate, clip_duration_ms, window_size_ms, + window_stride_ms, dct_coefficient_count) + + audio_processor = input_data.AudioProcessor( + FLAGS.data_url, FLAGS.data_dir, FLAGS.silence_percentage, + FLAGS.unknown_percentage, + FLAGS.wanted_words.split(','), FLAGS.validation_percentage, + FLAGS.testing_percentage, model_settings) + + label_count = model_settings['label_count'] + fingerprint_size = model_settings['fingerprint_size'] + + fingerprint_input = tf.placeholder( + tf.float32, [None, fingerprint_size], name='fingerprint_input') + + logits = models.create_model( + fingerprint_input, + model_settings, + FLAGS.model_architecture, + FLAGS.model_size_info, + FLAGS.act_max, + is_training=False) + + ground_truth_input = tf.placeholder( + tf.float32, [None, label_count], name='groundtruth_input') + + predicted_indices = tf.argmax(logits, 1) + expected_indices = tf.argmax(ground_truth_input, 1) + correct_prediction = tf.equal(predicted_indices, expected_indices) + confusion_matrix = tf.confusion_matrix( + expected_indices, predicted_indices, num_classes=label_count) + evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) + models.load_variables_from_checkpoint(sess, FLAGS.checkpoint) + + + # Quantize weights to 8-bits using (min,max) and write to file + f = open('weights.h','wb') + f.close() + + for v in tf.trainable_variables(): + var_name = str(v.name) + var_values = sess.run(v) + min_value = var_values.min() + max_value = var_values.max() + int_bits = int(np.ceil(np.log2(max(abs(min_value),abs(max_value))))) + dec_bits = 7-int_bits + # convert to [-128,128) or int8 + var_values = np.round(var_values*2**dec_bits) + var_name = var_name.replace('/','_') + var_name = var_name.replace(':','_') + with open('weights.h','a') as f: + f.write('#define '+var_name+' {') + if(len(var_values.shape)>2): #convolution layer weights + transposed_wts = np.transpose(var_values,(3,0,1,2)) + else: #fully connected layer weights or biases of any layer + transposed_wts = np.transpose(var_values) + with open('weights.h','a') as f: + transposed_wts.tofile(f,sep=", ",format="%d") + f.write('}\n') + # convert back original range but quantized to 8-bits or 256 levels + var_values = var_values/(2**dec_bits) + # update the weights in tensorflow graph for quantizing the activations + var_values = sess.run(tf.assign(v,var_values)) + print(var_name+' number of wts/bias: '+str(var_values.shape)+\ + ' dec bits: '+str(dec_bits)+\ + ' max: ('+str(var_values.max())+','+str(max_value)+')'+\ + ' min: ('+str(var_values.min())+','+str(min_value)+')') + + # training set + set_size = audio_processor.set_size('training') + tf.logging.info('set_size=%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + training_fingerprints, training_ground_truth = ( + audio_processor.get_data(FLAGS.batch_size, i, model_settings, 0.0, + 0.0, 0, 'training', sess)) + training_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: training_fingerprints, + ground_truth_input: training_ground_truth, + }) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (training_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Training accuracy = %.2f%% (N=%d)' % + (total_accuracy * 100, set_size)) + + # validation set + set_size = audio_processor.set_size('validation') + tf.logging.info('set_size=%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + validation_fingerprints, validation_ground_truth = ( + audio_processor.get_data(FLAGS.batch_size, i, model_settings, 0.0, + 0.0, 0, 'validation', sess)) + validation_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: validation_fingerprints, + ground_truth_input: validation_ground_truth, + }) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (validation_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Validation accuracy = %.2f%% (N=%d)' % + (total_accuracy * 100, set_size)) + + # test set + set_size = audio_processor.set_size('testing') + tf.logging.info('set_size=%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + test_fingerprints, test_ground_truth = audio_processor.get_data( + FLAGS.batch_size, i, model_settings, 0.0, 0.0, 0, 'testing', sess) + test_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: test_fingerprints, + ground_truth_input: test_ground_truth, + }) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (test_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Test accuracy = %.2f%% (N=%d)' % (total_accuracy * 100, + set_size)) + +def main(_): + + # Create the model, load weights from checkpoint and run on train/val/test + run_quant_inference(FLAGS.wanted_words, FLAGS.sample_rate, + FLAGS.clip_duration_ms, FLAGS.window_size_ms, + FLAGS.window_stride_ms, FLAGS.dct_coefficient_count, + FLAGS.model_architecture, FLAGS.model_size_info) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--data_url', + type=str, + # pylint: disable=line-too-long + default='http://download.tensorflow.org/data/speech_commands_v0.02.tar.gz', + # pylint: enable=line-too-long + help='Location of speech training data archive on the web.') + parser.add_argument( + '--data_dir', + type=str, + default='/tmp/speech_dataset/', + help="""\ + Where to download the speech training data to. + """) + parser.add_argument( + '--silence_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be silence. + """) + parser.add_argument( + '--unknown_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be unknown words. + """) + parser.add_argument( + '--testing_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a test set.') + parser.add_argument( + '--validation_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a validation set.') + parser.add_argument( + '--sample_rate', + type=int, + default=16000, + help='Expected sample rate of the wavs',) + parser.add_argument( + '--clip_duration_ms', + type=int, + default=1000, + help='Expected duration in milliseconds of the wavs',) + parser.add_argument( + '--window_size_ms', + type=float, + default=30.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--window_stride_ms', + type=float, + default=10.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--dct_coefficient_count', + type=int, + default=40, + help='How many bins to use for the MFCC fingerprint',) + parser.add_argument( + '--batch_size', + type=int, + default=100, + help='How many items to train with at once',) + parser.add_argument( + '--wanted_words', + type=str, + default='yes,no,up,down,left,right,on,off,stop,go', + help='Words to use (others will be added to an unknown label)',) + parser.add_argument( + '--checkpoint', + type=str, + default='', + help='Checkpoint to load the weights from.') + parser.add_argument( + '--model_architecture', + type=str, + default='dnn', + help='What model architecture to use') + parser.add_argument( + '--model_size_info', + type=int, + nargs="+", + default=[128,128,128], + help='Model dimensions - different for various models') + parser.add_argument( + '--act_max', + type=float, + nargs="+", + default=[128,128,128], + help='activations max') + + FLAGS, unparsed = parser.parse_known_args() + tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/requirements.txt b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..b8e30388fdde93ee9700943c338216947b52ff4c --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/requirements.txt @@ -0,0 +1,5 @@ +numpy==1.19.5 +six==1.15.0 +tensorboard==1.15.0 +tensorflow==1.15.0 +tensorflow-estimator==1.15.1 diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test.py new file mode 100644 index 0000000000000000000000000000000000000000..b826b3b33165c9e46f6fa3567e7273d9253ede83 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test.py @@ -0,0 +1,287 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017 Arm Inc. All Rights Reserved. +# Adapted from freeze.py to run inference on train/val/test dataset on the +# trained model in the form of checkpoint +# +# + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import argparse +import os.path +import sys + +import tensorflow as tf +import input_data +import models + + +def run_inference(wanted_words, sample_rate, clip_duration_ms, + window_size_ms, window_stride_ms, dct_coefficient_count, + model_architecture, model_size_info): + """Creates an audio model with the nodes needed for inference. + + Uses the supplied arguments to create a model, and inserts the input and + output nodes that are needed to use the graph for inference. + + Args: + wanted_words: Comma-separated list of the words we're trying to recognize. + sample_rate: How many samples per second are in the input audio files. + clip_duration_ms: How many samples to analyze for the audio pattern. + window_size_ms: Time slice duration to estimate frequencies from. + window_stride_ms: How far apart time slices should be. + dct_coefficient_count: Number of frequency bands to analyze. + model_architecture: Name of the kind of model to generate. + model_size_info: Model dimensions : different lengths for different models + """ + + tf.logging.set_verbosity(tf.logging.INFO) + sess = tf.InteractiveSession(config=npu_config_proto()) + words_list = input_data.prepare_words_list(wanted_words.split(',')) + model_settings = models.prepare_model_settings( + len(words_list), sample_rate, clip_duration_ms, window_size_ms, + window_stride_ms, dct_coefficient_count) + + audio_processor = input_data.AudioProcessor( + FLAGS.data_url, FLAGS.data_dir, FLAGS.silence_percentage, + FLAGS.unknown_percentage, + FLAGS.wanted_words.split(','), FLAGS.validation_percentage, + FLAGS.testing_percentage, model_settings) + + label_count = model_settings['label_count'] + fingerprint_size = model_settings['fingerprint_size'] + + fingerprint_input = tf.placeholder( + tf.float32, [None, fingerprint_size], name='fingerprint_input') + + logits = models.create_model( + fingerprint_input, + model_settings, + FLAGS.model_architecture, + FLAGS.model_size_info, + is_training=False) + + ground_truth_input = tf.placeholder( + tf.float32, [None, label_count], name='groundtruth_input') + + predicted_indices = tf.argmax(logits, 1) + expected_indices = tf.argmax(ground_truth_input, 1) + correct_prediction = tf.equal(predicted_indices, expected_indices) + confusion_matrix = tf.confusion_matrix( + expected_indices, predicted_indices, num_classes=label_count) + evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) + models.load_variables_from_checkpoint(sess, FLAGS.checkpoint) + + # training set + set_size = audio_processor.set_size('training') + tf.logging.info('set_size=%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + training_fingerprints, training_ground_truth = ( + audio_processor.get_data(FLAGS.batch_size, i, model_settings, 0.0, + 0.0, 0, 'training', sess)) + training_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: training_fingerprints, + ground_truth_input: training_ground_truth, + }) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (training_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Training accuracy = %.2f%% (N=%d)' % + (total_accuracy * 100, set_size)) + + + # validation set + set_size = audio_processor.set_size('validation') + tf.logging.info('set_size=%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + validation_fingerprints, validation_ground_truth = ( + audio_processor.get_data(FLAGS.batch_size, i, model_settings, 0.0, + 0.0, 0, 'validation', sess)) + validation_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: validation_fingerprints, + ground_truth_input: validation_ground_truth, + }) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (validation_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Validation accuracy = %.2f%% (N=%d)' % + (total_accuracy * 100, set_size)) + + # test set + set_size = audio_processor.set_size('testing') + tf.logging.info('set_size=%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + test_fingerprints, test_ground_truth = audio_processor.get_data( + FLAGS.batch_size, i, model_settings, 0.0, 0.0, 0, 'testing', sess) + test_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: test_fingerprints, + ground_truth_input: test_ground_truth, + }) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (test_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Test accuracy = %.2f%% (N=%d)' % (total_accuracy * 100, + set_size)) + +def main(_): + + # Create the model, load weights from checkpoint and run on train/val/test + run_inference(FLAGS.wanted_words, FLAGS.sample_rate, + FLAGS.clip_duration_ms, FLAGS.window_size_ms, + FLAGS.window_stride_ms, FLAGS.dct_coefficient_count, + FLAGS.model_architecture, FLAGS.model_size_info) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--data_url', + type=str, + # pylint: disable=line-too-long + default='http://download.tensorflow.org/data/speech_commands_v0.02.tar.gz', + # pylint: enable=line-too-long + help='Location of speech training data archive on the web.') + parser.add_argument( + '--data_dir', + type=str, + default='/tmp/speech_dataset/', + help="""\ + Where to download the speech training data to. + """) + parser.add_argument( + '--silence_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be silence. + """) + parser.add_argument( + '--unknown_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be unknown words. + """) + parser.add_argument( + '--testing_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a test set.') + parser.add_argument( + '--validation_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a validation set.') + parser.add_argument( + '--sample_rate', + type=int, + default=16000, + help='Expected sample rate of the wavs',) + parser.add_argument( + '--clip_duration_ms', + type=int, + default=1000, + help='Expected duration in milliseconds of the wavs',) + parser.add_argument( + '--window_size_ms', + type=float, + default=30.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--window_stride_ms', + type=float, + default=10.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--dct_coefficient_count', + type=int, + default=40, + help='How many bins to use for the MFCC fingerprint',) + parser.add_argument( + '--batch_size', + type=int, + default=100, + help='How many items to train with at once',) + parser.add_argument( + '--wanted_words', + type=str, + default='yes,no,up,down,left,right,on,off,stop,go', + help='Words to use (others will be added to an unknown label)',) + parser.add_argument( + '--checkpoint', + type=str, + default='', + help='Checkpoint to load the weights from.') + parser.add_argument( + '--model_architecture', + type=str, + default='dnn', + help='What model architecture to use') + parser.add_argument( + '--model_size_info', + type=int, + nargs="+", + default=[128,128,128], + help='Model dimensions - different for various models') + + FLAGS, unparsed = parser.parse_known_args() + tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_RT2_performance_1p.sh b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_RT2_performance_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..3cc15b418be92d6dfa9be051b2978b2e38ab314a --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_RT2_performance_1p.sh @@ -0,0 +1,210 @@ +#!/bin/bash +#当前路径,不需要修改 +cur_path=`pwd` +#集合通信参数,不需要修改 + +export RANK_SIZE=1 +export JOB_ID=10087 + +RANK_ID_START=0 + +#使能RT2.0 +export ENABLE_RUNTIME_V2=1 + +# 数据集路径,保持为空,不需要修改 +data_path="" + +#设置默认日志级别,不需要修改 +#export ASCEND_GLOBAL_LOG_LEVEL=1 + +#基础参数,需要模型审视修改 +#网络名称,同目录名称 +#ID1900_CarPeting_tf115_mobilebert +Network="DS-CNN_ID1769_for_TensorFlow" +batch_size=100 +#train_steps=30000 + +#维测参数,precision_mode需要模型审视修改 +precision_mode="allow_mix_precision" +#维持参数,以下不需要修改 +over_dump=False +data_dump_flag=False +data_dump_step="10" +profiling=False +autotune=False + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_performance_1p.sh " + echo " " + echo "parameter explain: + --precision_mode precision mode(allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision) + -h/--help show help message + " + exit 1 +fi + +#参数校验,不需要修改 +for para in $* +do + if [[ $para == --precision_mode* ]];then + precision_mode=`echo ${para#*=}` + elif [[ $para == --over_dump* ]];then + over_dump=`echo ${para#*=}` + over_dump_path=${cur_path}/output/overflow_dump + mkdir -p ${over_dump_path} + elif [[ $para == --data_dump_flag* ]];then + data_dump_flag=`echo ${para#*=}` + data_dump_path=${cur_path}/output/data_dump + mkdir -p ${data_dump_path} + elif [[ $para == --data_dump_step* ]];then + data_dump_step=`echo ${para#*=}` + elif [[ $para == --profiling* ]];then + profiling=`echo ${para#*=}` + profiling_dump_path=${cur_path}/output/profiling + mkdir -p ${profiling_dump_path} + elif [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + fi +done + + +#data_path='../' +#校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be confing" + exit 1 +fi + +#训练开始时间,不需要修改 +start_time=$(date +%s) +cd $cur_path/.. +mkdir -p logs/checkpoints/ + +#sed -i "s|tmp|${data_path}/data|g" run_squad.py +#sed -i "s|./speech_dataset/|${data_path}/|g" train.py + + +#进入训练脚本目录,需要模型审视修改 +for((RANK_ID=$RANK_ID_START;RANK_ID<$((RANK_SIZE+RANK_ID_START));RANK_ID++)); +do + #设置环境变量,不需要修改 + echo "Device ID: $ASCEND_DEVICE_ID" + export RANK_ID=$RANK_ID + + #创建DeviceID输出目录,不需要修改 + if [ -d ${cur_path}/output/${ASCEND_DEVICE_ID} ];then + rm -rf ${cur_path}/output/${ASCEND_DEVICE_ID} + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + else + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + fi + +# #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 +# #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path,--autotune +# nohup python3.7 $cur_path/../train_adda_seg.py ${data_path}/data/inria_test source_image source_label_index target_image adda_deeplab_v3p.h5 \ +# --optimizer adam \ +# --base_learning_rate 1e-4 \ +# --min_learning_rate 1e-7 \ +# --image_width 256 \ +# --image_height 256 \ +# --image_channel 3 \ +# --image_suffix .png \ +# --label_suffix .png \ +# --n_class 2 \ +# --batch_size 2 \ +# --iterations 50 \ +# --weight_decay 1e-4 \ +# --initializer he_normal \ +# --bn_epsilon 1e-3 \ +# --bn_momentum 0.99 \ +# --pre_trained_model ./logs/checkpoints/deeplab_v3p_base.h5 \ +# --source_fname_file ${data_path}/data/inria_test/source.txt \ +# --target_fname_file ${data_path}/data/inria_test/target.txt \ +# --logs_dir ./logs \ +# --augmentations flip_x,flip_y,random_crop \ +# --display 1 \ +# --snapshot 5 > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & + + echo "data_path is : " + echo "data_path is : $data_path" + #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 + #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path,--autotune + python3 train.py \ + --model_architecture ds_cnn \ + --model_size_info 5 64 10 4 2 2 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 \ + --dct_coefficient_count 10 \ + --window_size_ms 40 \ + --window_stride_ms 20 \ + --learning_rate 0.0005,0.0001,0.00002 \ + --how_many_training_steps 100,100,100 \ + --summaries_dir ./result/work/DS_CNN/DS_CNN_1/retrain_logs \ + --data_dir ${data_path} \ + --batch_size ${batch_size} \ + --train_dir ./result/work/DS_CNN/DS_CNN_1/training > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & +done +wait + +#sed -i "s|${data_path}/|./speech_dataset/|g" train.py +#sed -i "s|${data_path}/tmp|tmp|g" train.py +cd test + +#训练结束时间,不需要修改 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +#结果打印,不需要修改 +echo "------------------ Final result ------------------" +#输出性能FPS,需要模型审视修改 +#h_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $1}'` +#m_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $2}'` +#s_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $3}'` +#h_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $1}'` +#m_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $2}'` +#s_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $3}'` +#step_sec=`awk 'BEGIN{printf "%.2f\n",('${h_step_100}'-'${h_step_2}')*3600+('${m_step_100}'-'${m_step_2}')*60+('${s_step_100}'-'${s_step_2}')}'` + +data_step_sec=`grep 'train duration:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|grep -v INFO|awk 'NR>1'|awk '{print $5}'|awk '{sum+=$1} END {print sum/NR}'` +train_step_sec=`grep 'train duration:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|grep -v INFO|awk 'NR>1'|awk '{print $8}'|awk '{sum+=$1} END {print sum/NR}'` +step_sec=`awk 'BEGIN{printf "%.6f\n",'${data_step_sec}'+'${train_step_sec}'}'` +step_per_s=`awk 'BEGIN{printf "%.4f\n",1/'${step_sec}'}'` +FPS=`awk 'BEGIN{printf "%.2f\n",'${batch_size}'*'${step_per_s}'}'` +#打印,不需要修改 +echo "Final Performance images/sec : $FPS" + +#输出训练精度,需要模型审视修改 +train_accuracy=`grep 'INFO:tensorflow.*Validation accuracy' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $6}'|awk -F % 'END {print $1}'` +train_accuracy=`awk 'BEGIN{printf "%.4f\n",'${train_accuracy}'/100}'` +#打印,不需要修改 +echo "Final Train Accuracy : ${train_accuracy}" +echo "E2E Training Duration sec : $e2e_time" + +#稳定性精度看护结果汇总 +#训练用例信息,不需要修改 +BatchSize=${batch_size} +DeviceType=`uname -m` +CaseName=${Network}_bs${BatchSize}_${RANK_SIZE}'p'_'RT2'_'perf' + +##获取性能数据 +#吞吐量,不需要修改 +ActualFPS=${FPS} +#单迭代训练时长,不需要修改 +TrainingTime=`awk 'BEGIN{printf "%.2f\n",'${BatchSize}'/'${FPS}'}'` + +#从train_$ASCEND_DEVICE_ID.log提取Loss到train_${CaseName}_loss.txt中,需要根据模型审视 +grep 'INFO:tensorflow.*cross entropy' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk '{print $9}' > $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt + +#最后一个迭代loss值,不需要修改 +ActualLoss=`awk 'END {print}' $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt` + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${BatchSize}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = ${DeviceType}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${ActualFPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${TrainingTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainAccuracy = ${train_accuracy}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_full_1p.sh b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_full_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..dd87cda39e8d3a559038b36cffa51558e332db5d --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_full_1p.sh @@ -0,0 +1,208 @@ +#!/bin/bash +#当前路径,不需要修改 +cur_path=`pwd` +#集合通信参数,不需要修改 + +export RANK_SIZE=1 +export JOB_ID=10087 + +RANK_ID_START=0 + + +# 数据集路径,保持为空,不需要修改 +data_path="" + +#设置默认日志级别,不需要修改 +#export ASCEND_GLOBAL_LOG_LEVEL=1 + +#基础参数,需要模型审视修改 +#网络名称,同目录名称 +#ID1900_CarPeting_tf115_mobilebert +Network="DS-CNN_ID1769_for_TensorFlow" +batch_size=100 +train_steps=30000 + +#维测参数,precision_mode需要模型审视修改 +precision_mode="allow_mix_precision" +#维持参数,以下不需要修改 +over_dump=False +data_dump_flag=False +data_dump_step="10" +profiling=False +autotune=False + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_full_1p.sh " + echo " " + echo "parameter explain: + --precision_mode precision mode(allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision) + -h/--help show help message + " + exit 1 +fi + +#参数校验,不需要修改 +for para in $* +do + if [[ $para == --precision_mode* ]];then + precision_mode=`echo ${para#*=}` + elif [[ $para == --over_dump* ]];then + over_dump=`echo ${para#*=}` + over_dump_path=${cur_path}/output/overflow_dump + mkdir -p ${over_dump_path} + elif [[ $para == --data_dump_flag* ]];then + data_dump_flag=`echo ${para#*=}` + data_dump_path=${cur_path}/output/data_dump + mkdir -p ${data_dump_path} + elif [[ $para == --data_dump_step* ]];then + data_dump_step=`echo ${para#*=}` + elif [[ $para == --profiling* ]];then + profiling=`echo ${para#*=}` + profiling_dump_path=${cur_path}/output/profiling + mkdir -p ${profiling_dump_path} + elif [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + fi +done + + +#data_path='../' +#校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be confing" + exit 1 +fi + +#训练开始时间,不需要修改 +start_time=$(date +%s) +cd $cur_path/.. +mkdir -p logs/checkpoints/ + +#sed -i "s|tmp|${data_path}/data|g" run_squad.py +#sed -i "s|./speech_dataset/|${data_path}/|g" train.py + + +#进入训练脚本目录,需要模型审视修改 +for((RANK_ID=$RANK_ID_START;RANK_ID<$((RANK_SIZE+RANK_ID_START));RANK_ID++)); +do + #设置环境变量,不需要修改 + echo "Device ID: $ASCEND_DEVICE_ID" + export RANK_ID=$RANK_ID + + #创建DeviceID输出目录,不需要修改 + if [ -d ${cur_path}/output/${ASCEND_DEVICE_ID} ];then + rm -rf ${cur_path}/output/${ASCEND_DEVICE_ID} + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + else + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + fi + +# #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 +# #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path,--autotune +# nohup python3.7 $cur_path/../train_adda_seg.py ${data_path}/data/inria_test source_image source_label_index target_image adda_deeplab_v3p.h5 \ +# --optimizer adam \ +# --base_learning_rate 1e-4 \ +# --min_learning_rate 1e-7 \ +# --image_width 256 \ +# --image_height 256 \ +# --image_channel 3 \ +# --image_suffix .png \ +# --label_suffix .png \ +# --n_class 2 \ +# --batch_size 2 \ +# --iterations 50 \ +# --weight_decay 1e-4 \ +# --initializer he_normal \ +# --bn_epsilon 1e-3 \ +# --bn_momentum 0.99 \ +# --pre_trained_model ./logs/checkpoints/deeplab_v3p_base.h5 \ +# --source_fname_file ${data_path}/data/inria_test/source.txt \ +# --target_fname_file ${data_path}/data/inria_test/target.txt \ +# --logs_dir ./logs \ +# --augmentations flip_x,flip_y,random_crop \ +# --display 1 \ +# --snapshot 5 > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & + + echo "data_path is : " + echo "data_path is : $data_path" + #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 + #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path,--autotune + python3 train.py \ + --model_architecture ds_cnn \ + --model_size_info 5 64 10 4 2 2 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 \ + --dct_coefficient_count 10 \ + --window_size_ms 40 \ + --window_stride_ms 20 \ + --learning_rate 0.0005,0.0001,0.00002 \ + --how_many_training_steps 10000,10000,10000 \ + --summaries_dir ./result/work/DS_CNN/DS_CNN_1/retrain_logs \ + --data_dir ${data_path} \ + --batch_size ${batch_size} \ + --train_dir ./result/work/DS_CNN/DS_CNN_1/training > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & +done +wait + +#sed -i "s|${data_path}/|./speech_dataset/|g" train.py +#sed -i "s|${data_path}/tmp|tmp|g" train.py +cd test + +#训练结束时间,不需要修改 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +#结果打印,不需要修改 +echo "------------------ Final result ------------------" +#输出性能FPS,需要模型审视修改 +#h_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $1}'` +#m_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $2}'` +#s_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $3}'` +#h_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $1}'` +#m_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $2}'` +#s_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $3}'` +#step_sec=`awk 'BEGIN{printf "%.2f\n",('${h_step_100}'-'${h_step_2}')*3600+('${m_step_100}'-'${m_step_2}')*60+('${s_step_100}'-'${s_step_2}')}'` + +data_step_sec=`grep 'train duration:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $5}'` +train_step_sec=`grep 'train duration:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $8}'` +step_sec=`awk 'BEGIN{printf "%.6f\n",'${data_step_sec}'+'${train_step_sec}'}'` +step_per_s=`awk 'BEGIN{printf "%.4f\n",1/'${step_sec}'}'` +FPS=`awk 'BEGIN{printf "%.2f\n",'${batch_size}'*'${step_per_s}'}'` +#打印,不需要修改 +echo "Final Performance images/sec : $FPS" + +#输出训练精度,需要模型审视修改 +train_accuracy=`grep 'INFO:tensorflow.*Validation accuracy' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $6}'|awk -F % 'END {print $1}'` +train_accuracy=`awk 'BEGIN{printf "%.4f\n",'${train_accuracy}'/100}'` +#打印,不需要修改 +echo "Final Train Accuracy : ${train_accuracy}" +echo "E2E Training Duration sec : $e2e_time" + +#稳定性精度看护结果汇总 +#训练用例信息,不需要修改 +BatchSize=${batch_size} +DeviceType=`uname -m` +CaseName=${Network}_bs${BatchSize}_${RANK_SIZE}'p'_'acc' + +##获取性能数据 +#吞吐量,不需要修改 +ActualFPS=${FPS} +#单迭代训练时长,不需要修改 +TrainingTime=`awk 'BEGIN{printf "%.2f\n",'${BatchSize}'/'${FPS}'}'` + +#从train_$ASCEND_DEVICE_ID.log提取Loss到train_${CaseName}_loss.txt中,需要根据模型审视 +grep 'INFO:tensorflow.*cross entropy' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk '{print $9}' > $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt + +#最后一个迭代loss值,不需要修改 +ActualLoss=`awk 'END {print}' $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt` + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${BatchSize}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = ${DeviceType}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${ActualFPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${TrainingTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainAccuracy = ${train_accuracy}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log \ No newline at end of file diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_performance_1p.sh b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_performance_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..19c6b0fa0c04d3d5c536dbd9239f4a2979b7047c --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test/train_performance_1p.sh @@ -0,0 +1,208 @@ +#!/bin/bash +#当前路径,不需要修改 +cur_path=`pwd` +#集合通信参数,不需要修改 + +export RANK_SIZE=1 +export JOB_ID=10087 + +RANK_ID_START=0 + + +# 数据集路径,保持为空,不需要修改 +data_path="" + +#设置默认日志级别,不需要修改 +#export ASCEND_GLOBAL_LOG_LEVEL=1 + +#基础参数,需要模型审视修改 +#网络名称,同目录名称 +#ID1900_CarPeting_tf115_mobilebert +Network="DS-CNN_ID1769_for_TensorFlow" +batch_size=100 +#train_steps=30000 + +#维测参数,precision_mode需要模型审视修改 +precision_mode="allow_mix_precision" +#维持参数,以下不需要修改 +over_dump=False +data_dump_flag=False +data_dump_step="10" +profiling=False +autotune=False + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_performance_1p.sh " + echo " " + echo "parameter explain: + --precision_mode precision mode(allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision) + -h/--help show help message + " + exit 1 +fi + +#参数校验,不需要修改 +for para in $* +do + if [[ $para == --precision_mode* ]];then + precision_mode=`echo ${para#*=}` + elif [[ $para == --over_dump* ]];then + over_dump=`echo ${para#*=}` + over_dump_path=${cur_path}/output/overflow_dump + mkdir -p ${over_dump_path} + elif [[ $para == --data_dump_flag* ]];then + data_dump_flag=`echo ${para#*=}` + data_dump_path=${cur_path}/output/data_dump + mkdir -p ${data_dump_path} + elif [[ $para == --data_dump_step* ]];then + data_dump_step=`echo ${para#*=}` + elif [[ $para == --profiling* ]];then + profiling=`echo ${para#*=}` + profiling_dump_path=${cur_path}/output/profiling + mkdir -p ${profiling_dump_path} + elif [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + fi +done + + +#data_path='../' +#校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be confing" + exit 1 +fi + +#训练开始时间,不需要修改 +start_time=$(date +%s) +cd $cur_path/.. +mkdir -p logs/checkpoints/ + +#sed -i "s|tmp|${data_path}/data|g" run_squad.py +#sed -i "s|./speech_dataset/|${data_path}/|g" train.py + + +#进入训练脚本目录,需要模型审视修改 +for((RANK_ID=$RANK_ID_START;RANK_ID<$((RANK_SIZE+RANK_ID_START));RANK_ID++)); +do + #设置环境变量,不需要修改 + echo "Device ID: $ASCEND_DEVICE_ID" + export RANK_ID=$RANK_ID + + #创建DeviceID输出目录,不需要修改 + if [ -d ${cur_path}/output/${ASCEND_DEVICE_ID} ];then + rm -rf ${cur_path}/output/${ASCEND_DEVICE_ID} + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + else + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + fi + +# #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 +# #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path,--autotune +# nohup python3.7 $cur_path/../train_adda_seg.py ${data_path}/data/inria_test source_image source_label_index target_image adda_deeplab_v3p.h5 \ +# --optimizer adam \ +# --base_learning_rate 1e-4 \ +# --min_learning_rate 1e-7 \ +# --image_width 256 \ +# --image_height 256 \ +# --image_channel 3 \ +# --image_suffix .png \ +# --label_suffix .png \ +# --n_class 2 \ +# --batch_size 2 \ +# --iterations 50 \ +# --weight_decay 1e-4 \ +# --initializer he_normal \ +# --bn_epsilon 1e-3 \ +# --bn_momentum 0.99 \ +# --pre_trained_model ./logs/checkpoints/deeplab_v3p_base.h5 \ +# --source_fname_file ${data_path}/data/inria_test/source.txt \ +# --target_fname_file ${data_path}/data/inria_test/target.txt \ +# --logs_dir ./logs \ +# --augmentations flip_x,flip_y,random_crop \ +# --display 1 \ +# --snapshot 5 > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & + + echo "data_path is : " + echo "data_path is : $data_path" + #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 + #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path,--autotune + python3 train.py \ + --model_architecture ds_cnn \ + --model_size_info 5 64 10 4 2 2 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 \ + --dct_coefficient_count 10 \ + --window_size_ms 40 \ + --window_stride_ms 20 \ + --learning_rate 0.0005,0.0001,0.00002 \ + --how_many_training_steps 100,100,100 \ + --summaries_dir ./result/work/DS_CNN/DS_CNN_1/retrain_logs \ + --data_dir ${data_path} \ + --batch_size ${batch_size} \ + --train_dir ./result/work/DS_CNN/DS_CNN_1/training > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & +done +wait + +#sed -i "s|${data_path}/|./speech_dataset/|g" train.py +#sed -i "s|${data_path}/tmp|tmp|g" train.py +cd test + +#训练结束时间,不需要修改 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +#结果打印,不需要修改 +echo "------------------ Final result ------------------" +#输出性能FPS,需要模型审视修改 +#h_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $1}'` +#m_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $2}'` +#s_step_2=`grep ' Step #2:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $3}'` +#h_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $1}'` +#m_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $2}'` +#s_step_100=`grep ' Step #100:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $2}'|awk -F . '{print $1}'|awk -F : '{print $3}'` +#step_sec=`awk 'BEGIN{printf "%.2f\n",('${h_step_100}'-'${h_step_2}')*3600+('${m_step_100}'-'${m_step_2}')*60+('${s_step_100}'-'${s_step_2}')}'` + +data_step_sec=`grep 'train duration:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|grep -v INFO|awk 'NR>1'|awk '{print $5}'|awk '{sum+=$1} END {print sum/NR}'` +train_step_sec=`grep 'train duration:' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|grep -v INFO|awk 'NR>1'|awk '{print $8}'|awk '{sum+=$1} END {print sum/NR}'` +step_sec=`awk 'BEGIN{printf "%.6f\n",'${data_step_sec}'+'${train_step_sec}'}'` +step_per_s=`awk 'BEGIN{printf "%.4f\n",1/'${step_sec}'}'` +FPS=`awk 'BEGIN{printf "%.2f\n",'${batch_size}'*'${step_per_s}'}'` +#打印,不需要修改 +echo "Final Performance images/sec : $FPS" + +#输出训练精度,需要模型审视修改 +train_accuracy=`grep 'INFO:tensorflow.*Validation accuracy' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk 'END {print $6}'|awk -F % 'END {print $1}'` +train_accuracy=`awk 'BEGIN{printf "%.4f\n",'${train_accuracy}'/100}'` +#打印,不需要修改 +echo "Final Train Accuracy : ${train_accuracy}" +echo "E2E Training Duration sec : $e2e_time" + +#稳定性精度看护结果汇总 +#训练用例信息,不需要修改 +BatchSize=${batch_size} +DeviceType=`uname -m` +CaseName=${Network}_bs${BatchSize}_${RANK_SIZE}'p'_'perf' + +##获取性能数据 +#吞吐量,不需要修改 +ActualFPS=${FPS} +#单迭代训练时长,不需要修改 +TrainingTime=`awk 'BEGIN{printf "%.2f\n",'${BatchSize}'/'${FPS}'}'` + +#从train_$ASCEND_DEVICE_ID.log提取Loss到train_${CaseName}_loss.txt中,需要根据模型审视 +grep 'INFO:tensorflow.*cross entropy' $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk '{print $9}' > $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt + +#最后一个迭代loss值,不需要修改 +ActualLoss=`awk 'END {print}' $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt` + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${BatchSize}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = ${DeviceType}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${ActualFPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${TrainingTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainAccuracy = ${train_accuracy}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log \ No newline at end of file diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test_pb.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test_pb.py new file mode 100644 index 0000000000000000000000000000000000000000..649327ab7400b551eccc303f66eae8a6864c4147 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/test_pb.py @@ -0,0 +1,288 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017-18 Arm Inc. All Rights Reserved. +# Adapted from freeze.py to run inference on train/val/test dataset on the +# trained model in the form of pb +# +# + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import argparse +import os.path +import sys + +import tensorflow as tf +import input_data +import models + + +def load_graph(filename): + """Unpersists graph from file as default graph.""" + with tf.gfile.FastGFile(filename, 'rb') as f: + graph_def = tf.GraphDef() + graph_def.ParseFromString(f.read()) + tf.import_graph_def(graph_def, name='') + +def run_inference_pb(wanted_words, sample_rate, clip_duration_ms, + window_size_ms, window_stride_ms, dct_coefficient_count, + model_architecture, model_size_info): + """Creates an audio model with the nodes needed for inference. + + Uses the supplied arguments to create a model, and inserts the input and + output nodes that are needed to use the graph for inference. + + Args: + wanted_words: Comma-separated list of the words we're trying to recognize. + sample_rate: How many samples per second are in the input audio files. + clip_duration_ms: How many samples to analyze for the audio pattern. + window_size_ms: Time slice duration to estimate frequencies from. + window_stride_ms: How far apart time slices should be. + dct_coefficient_count: Number of frequency bands to analyze. + model_architecture: Name of the kind of model to generate. + model_size_info: Model dimensions : different lengths for different models + """ + + tf.logging.set_verbosity(tf.logging.INFO) + sess = tf.InteractiveSession(config=npu_config_proto()) + words_list = input_data.prepare_words_list(wanted_words.split(',')) + model_settings = models.prepare_model_settings( + len(words_list), sample_rate, clip_duration_ms, window_size_ms, + window_stride_ms, dct_coefficient_count) + + load_graph(FLAGS.graph) + + audio_processor = input_data.AudioProcessor( + FLAGS.data_url, FLAGS.data_dir, FLAGS.silence_percentage, + FLAGS.unknown_percentage, + FLAGS.wanted_words.split(','), FLAGS.validation_percentage, + FLAGS.testing_percentage, model_settings) + + softmax = sess.graph.get_tensor_by_name("labels_softmax:0") + + label_count = model_settings['label_count'] + + ground_truth_input = tf.placeholder( + tf.float32, [None, label_count], name='groundtruth_input') + + predicted_indices = tf.argmax(softmax, 1) + expected_indices = tf.argmax(ground_truth_input, 1) + correct_prediction = tf.equal(predicted_indices, expected_indices) + confusion_matrix = tf.confusion_matrix( + expected_indices, predicted_indices, num_classes=label_count) + evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) + + if(FLAGS.training): + # training set + set_size = audio_processor.set_size('training') + tf.logging.info('Training set size:%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in range(0, set_size): + training_file, training_ground_truth = ( + audio_processor.get_wav_files(1, i, model_settings, 'training')) + with open(training_file[0], 'rb') as wav_file: + training_data = wav_file.read() + training_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + 'wav_data:0': training_data, + ground_truth_input: training_ground_truth, + }) + total_accuracy += (training_accuracy) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Training accuracy = %.2f%% (N=%d)' % (total_accuracy * 100, + set_size)) + + # validation set + set_size = audio_processor.set_size('validation') + tf.logging.info('Validation set size:%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in range(0, set_size): + validation_file, validation_ground_truth = ( + audio_processor.get_wav_files(1, i, model_settings, 'validation')) + with open(validation_file[0], 'rb') as wav_file: + validation_data = wav_file.read() + validation_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + 'wav_data:0': validation_data, + ground_truth_input: validation_ground_truth, + }) + total_accuracy += (validation_accuracy) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Validation accuracy = %.2f%% (N=%d)' % + (total_accuracy * 100, set_size)) + # test set + set_size = audio_processor.set_size('testing') + tf.logging.info('Test set size:%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in range(0, set_size): + test_file, test_ground_truth = ( + audio_processor.get_wav_files(1, i, model_settings, 'testing')) + with open(test_file[0], 'rb') as wav_file: + test_data = wav_file.read() + test_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + 'wav_data:0': test_data, + ground_truth_input: test_ground_truth, + }) + total_accuracy += (test_accuracy) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Test accuracy = %.2f%% (N=%d)' % (total_accuracy * 100, + set_size)) + +def main(_): + + # Create the model, load weights from pb and run on train/val/test + run_inference_pb(FLAGS.wanted_words, FLAGS.sample_rate, + FLAGS.clip_duration_ms, FLAGS.window_size_ms, + FLAGS.window_stride_ms, FLAGS.dct_coefficient_count, + FLAGS.model_architecture, FLAGS.model_size_info) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--data_url', + type=str, + # pylint: disable=line-too-long + default='http://download.tensorflow.org/data/speech_commands_v0.02.tar.gz', + # pylint: enable=line-too-long + help='Location of speech training data archive on the web.') + parser.add_argument( + '--data_dir', + type=str, + default='/tmp/speech_dataset/', + help="""\ + Where to download the speech training data to. + """) + parser.add_argument( + '--graph', type=str, default='', help='Model to use for identification.') + parser.add_argument( + '--silence_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be silence. + """) + parser.add_argument( + '--unknown_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be unknown words. + """) + parser.add_argument( + '--testing_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a test set.') + parser.add_argument( + '--validation_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a validation set.') + parser.add_argument( + '--sample_rate', + type=int, + default=16000, + help='Expected sample rate of the wavs',) + parser.add_argument( + '--clip_duration_ms', + type=int, + default=1000, + help='Expected duration in milliseconds of the wavs',) + parser.add_argument( + '--window_size_ms', + type=float, + default=30.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--window_stride_ms', + type=float, + default=10.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--dct_coefficient_count', + type=int, + default=40, + help='How many bins to use for the MFCC fingerprint',) + parser.add_argument( + '--batch_size', + type=int, + default=100, + help='How many items to train with at once',) + parser.add_argument( + '--wanted_words', + type=str, + default='yes,no,up,down,left,right,on,off,stop,go', + help='Words to use (others will be added to an unknown label)',) + parser.add_argument( + '--model_architecture', + type=str, + default='dnn', + help='What model architecture to use') + parser.add_argument( + '--model_size_info', + type=int, + nargs="+", + default=[128,128,128], + help='Model dimensions - different for various models') + parser.add_argument( + '--training', + action='store_true', + default=False, + help='run on training (1) or not (0)',) + + FLAGS, unparsed = parser.parse_known_args() + tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/train.py b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/train.py new file mode 100644 index 0000000000000000000000000000000000000000..112252bb7e28fdff5f72d82d3f5d1b89e5770f21 --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/train.py @@ -0,0 +1,520 @@ +#!/usr/bin/env python +# coding=utf-8 + +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# +# Modifications Copyright 2017 Arm Inc. All Rights Reserved. +# Added model dimensions as command line argument and changed to Adam optimizer +# +# +"""Simple speech recognition to spot a limited number of keywords. + +This is a self-contained example script that will train a very basic audio +recognition model in TensorFlow. It downloads the necessary training data and +runs with reasonable defaults to train within a few hours even only using a CPU. +For more information, please see +https://www.tensorflow.org/tutorials/audio_recognition. + +It is intended as an introduction to using neural networks for audio +recognition, and is not a full speech recognition system. For more advanced +speech systems, I recommend looking into Kaldi. This network uses a keyword +detection style to spot discrete words from a small vocabulary, consisting of +"yes", "no", "up", "down", "left", "right", "on", "off", "stop", and "go". + +To run the training process, use: + +bazel run tensorflow/examples/speech_commands:train + +This will write out checkpoints to /tmp/speech_commands_train/, and will +download over 1GB of open source training data, so you'll need enough free space +and a good internet connection. The default data is a collection of thousands of +one-second .wav files, each containing one spoken word. This data set is +collected from https://aiyprojects.withgoogle.com/open_speech_recording, please +consider contributing to help improve this and other models! + +As training progresses, it will print out its accuracy metrics, which should +rise above 90% by the end. Once it's complete, you can run the freeze script to +get a binary GraphDef that you can easily deploy on mobile applications. + +If you want to train on your own data, you'll need to create .wavs with your +recordings, all at a consistent length, and then arrange them into subfolders +organized by label. For example, here's a possible file structure: + +my_wavs > + up > + audio_0.wav + audio_1.wav + down > + audio_2.wav + audio_3.wav + other> + audio_4.wav + audio_5.wav + +You'll also need to tell the script what labels to look for, using the +`--wanted_words` argument. In this case, 'up,down' might be what you want, and +the audio in the 'other' folder would be used to train an 'unknown' category. + +To pull this all together, you'd run: + +bazel run tensorflow/examples/speech_commands:train -- \ +--data_dir=my_wavs --wanted_words=up,down + +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from npu_bridge.npu_init import * + +import argparse +import os.path +import sys + +import numpy as np +from six.moves import xrange # pylint: disable=redefined-builtin +import tensorflow as tf + +import input_data +import models +from tensorflow.python.platform import gfile +from tensorflow.contrib import slim as slim +import time + +FLAGS = None + + +def main(_): + # We want to see all the logging messages for this tutorial. + tf.logging.set_verbosity(tf.logging.INFO) + + ################################################## + global_config = tf.ConfigProto(log_device_placement=False) + custom_op = global_config.graph_options.rewrite_options.custom_optimizers.add() + custom_op.name = 'NpuOptimizer' + custom_op.parameter_map['precision_mode'].s = tf.compat.as_bytes('allow_mix_precision') + #custom_op.parameter_map['dynamic_input'].b = 1 + #custom_op.parameter_map['dynamic_graph_execute_mode'].s = tf.compat.as_bytes('lazy_recompile') + + ################################################## + + # Start a new TensorFlow session. + # sess = tf.InteractiveSession(config=npu_config_proto()) + sess = tf.InteractiveSession(config=global_config) + + # Begin by making sure we have the training data we need. If you already have + # training data of your own, use `--data_url= ` on the command line to avoid + # downloading. + model_settings = models.prepare_model_settings( + len(input_data.prepare_words_list(FLAGS.wanted_words.split(','))), + FLAGS.sample_rate, FLAGS.clip_duration_ms, FLAGS.window_size_ms, + FLAGS.window_stride_ms, FLAGS.dct_coefficient_count) + audio_processor = input_data.AudioProcessor( + FLAGS.data_url, FLAGS.data_dir, FLAGS.silence_percentage, + FLAGS.unknown_percentage, + FLAGS.wanted_words.split(','), FLAGS.validation_percentage, + FLAGS.testing_percentage, model_settings, sess) + fingerprint_size = model_settings['fingerprint_size'] + label_count = model_settings['label_count'] + time_shift_samples = int((FLAGS.time_shift_ms * FLAGS.sample_rate) / 1000) + # Figure out the learning rates for each training phase. Since it's often + # effective to have high learning rates at the start of training, followed by + # lower levels towards the end, the number of steps and learning rates can be + # specified as comma-separated lists to define the rate at each stage. For + # example --how_many_training_steps=10000,3000 --learning_rate=0.001,0.0001 + # will run 13,000 training loops in total, with a rate of 0.001 for the first + # 10,000, and 0.0001 for the final 3,000. + training_steps_list = list(map(int, FLAGS.how_many_training_steps.split(','))) + learning_rates_list = list(map(float, FLAGS.learning_rate.split(','))) + if len(training_steps_list) != len(learning_rates_list): + raise Exception( + '--how_many_training_steps and --learning_rate must be equal length ' + 'lists, but are %d and %d long instead' % (len(training_steps_list), + len(learning_rates_list))) + + fingerprint_input = tf.placeholder( + tf.float32, [None, fingerprint_size], name='fingerprint_input') + + logits, dropout_prob = models.create_model( + fingerprint_input, + model_settings, + FLAGS.model_architecture, + FLAGS.model_size_info, + is_training=True) + + # Define loss and optimizer + ground_truth_input = tf.placeholder( + tf.float32, [None, label_count], name='groundtruth_input') + + # Optionally we can add runtime checks to spot when NaNs or other symptoms of + # numerical errors start occurring during training. + control_dependencies = [] + if FLAGS.check_nans: + checks = tf.add_check_numerics_ops() + control_dependencies = [checks] + + # Create the back propagation and training evaluation machinery in the graph. + with tf.name_scope('cross_entropy'): + cross_entropy_mean = tf.reduce_mean( + tf.nn.softmax_cross_entropy_with_logits( + labels=ground_truth_input, logits=logits)) + #################### + #cross_entropy_mean = util.set_graph_exec_config(cross_entropy_mean,dynamic_input=True, + #dynamic_graph_execute_mode='dynamic_execute', + #dynamic_inputs_shape_range='data:[100,490],[100,12],[]') + #################### + tf.summary.scalar('cross_entropy', cross_entropy_mean) + + update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) + with tf.name_scope('train'), tf.control_dependencies(update_ops), tf.control_dependencies(control_dependencies): + learning_rate_input = tf.placeholder( + tf.float32, [], name='learning_rate_input') + train_op = tf.train.AdamOptimizer( + learning_rate_input) + train_step = slim.learning.create_train_op(cross_entropy_mean, train_op) +# train_step = tf.train.GradientDescentOptimizer( +# learning_rate_input).minimize(cross_entropy_mean) + predicted_indices = tf.argmax(logits, 1) + expected_indices = tf.argmax(ground_truth_input, 1) + correct_prediction = tf.equal(predicted_indices, expected_indices) + confusion_matrix = tf.confusion_matrix( + expected_indices, predicted_indices, num_classes=label_count) + ################### + #confusion_matrix = util.set_graph_exec_config(confusion_matrix,dynamic_input=True, + #dynamic_graph_execute_mode='dynamic_execute', + #dynamic_inputs_shape_range='data:[100,490],[100,12]') + ################### + evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) + tf.summary.scalar('accuracy', evaluation_step) + + global_step = tf.train.get_or_create_global_step() + increment_global_step = tf.assign(global_step, global_step + 1) + + saver = tf.train.Saver(tf.global_variables()) + + # Merge all the summaries and write them out to /tmp/retrain_logs (by default) + merged_summaries = tf.summary.merge_all() + train_writer = tf.summary.FileWriter(FLAGS.summaries_dir + '/train', + sess.graph) + validation_writer = tf.summary.FileWriter(FLAGS.summaries_dir + '/validation') + + tf.global_variables_initializer().run() + + # Parameter counts + params = tf.trainable_variables() + num_params = sum(map(lambda t: np.prod(tf.shape(t.value()).eval()), params)) + print('Total number of Parameters: ', num_params) + + start_step = 1 + + if FLAGS.start_checkpoint: + models.load_variables_from_checkpoint(sess, FLAGS.start_checkpoint) + start_step = global_step.eval(session=sess) + + tf.logging.info('Training from step: %d ', start_step) + + # Save graph.pbtxt. + tf.train.write_graph(sess.graph_def, FLAGS.train_dir, + FLAGS.model_architecture + '.pbtxt') + + # Save list of words. + with gfile.GFile( + os.path.join(FLAGS.train_dir, FLAGS.model_architecture + '_labels.txt'), + 'w') as f: + f.write('\n'.join(audio_processor.words_list)) + + # Training loop. + best_accuracy = 0 + training_steps_max = np.sum(training_steps_list) + tf.logging.info('**** start create dataset') + dataset_start = time.time() + dataset = audio_processor.create_dataset(training_steps_max, + FLAGS.batch_size, 0, model_settings, FLAGS.background_frequency, + FLAGS.background_volume, time_shift_samples, 'training', sess) + iterator = dataset.make_initializable_iterator() + audio_processor.train_fingerprints, audio_processor.train_ground_truth = iterator.get_next() + sess.run(iterator.initializer) + dataset_end = time.time() + + tf.logging.info('**** create dataset finished, duration: %.6f' % (dataset_end-dataset_start)) + + for training_step in xrange(start_step, training_steps_max + 1): + # Figure out what the current learning rate is. + training_steps_sum = 0 + for i in range(len(training_steps_list)): + training_steps_sum += training_steps_list[i] + if training_step <= training_steps_sum: + learning_rate_value = learning_rates_list[i] + break + data_start = time.time() + # Pull the audio samples we'll use for training. + ''' + train_fingerprints, train_ground_truth = audio_processor.get_data( + FLAGS.batch_size, 0, model_settings, FLAGS.background_frequency, + FLAGS.background_volume, time_shift_samples, 'training', sess) + ''' + train_fingerprints, train_ground_truth = sess.run([audio_processor.train_fingerprints, audio_processor.train_ground_truth]) + + start = time.time() + # Run the graph with this batch of training data. + train_summary, train_accuracy, cross_entropy_value, _, _ = sess.run( + [ + merged_summaries, evaluation_step, cross_entropy_mean, train_step, + increment_global_step + ], + feed_dict={ + fingerprint_input: train_fingerprints, + ground_truth_input: train_ground_truth, + learning_rate_input: learning_rate_value, + dropout_prob: 1.0 + }) + + end = time.time() + print('**** data prepare duration: {:.6f} train duration: {:.6f}'.format(start-data_start, end-start)) + + + train_writer.add_summary(train_summary, training_step) + tf.logging.info('Step #%d: rate %f, accuracy %.2f%%, cross entropy %f' % + (training_step, learning_rate_value, train_accuracy * 100, + cross_entropy_value)) + is_last_step = (training_step == training_steps_max) + if (training_step % FLAGS.eval_step_interval) == 0 or is_last_step: + set_size = audio_processor.set_size('validation') + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + validation_fingerprints, validation_ground_truth = ( + audio_processor.get_data(FLAGS.batch_size, i, model_settings, 0.0, + 0.0, 0, 'validation', sess)) + + # Run a validation step and capture training summaries for TensorBoard + # with the `merged` op. + validation_summary, validation_accuracy, conf_matrix = sess.run( + [merged_summaries, evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: validation_fingerprints, + ground_truth_input: validation_ground_truth, + dropout_prob: 1.0 + }) + validation_writer.add_summary(validation_summary, training_step) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (validation_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Step %d: Validation accuracy = %.2f%% (N=%d)' % + (training_step, total_accuracy * 100, set_size)) + + # Save the model checkpoint when validation accuracy improves + if total_accuracy > best_accuracy: + best_accuracy = total_accuracy + checkpoint_path = os.path.join(FLAGS.train_dir, 'best', + FLAGS.model_architecture + '_'+ str(int(best_accuracy*10000)) + '.ckpt') + tf.logging.info('Saving best model to "%s-%d"', checkpoint_path, training_step) + saver.save(sess, checkpoint_path, global_step=training_step) + tf.logging.info('So far the best validation accuracy is %.2f%%' % (best_accuracy*100)) + + set_size = audio_processor.set_size('testing') + tf.logging.info('set_size=%d', set_size) + total_accuracy = 0 + total_conf_matrix = None + for i in xrange(0, set_size, FLAGS.batch_size): + test_fingerprints, test_ground_truth = audio_processor.get_data( + FLAGS.batch_size, i, model_settings, 0.0, 0.0, 0, 'testing', sess) + test_accuracy, conf_matrix = sess.run( + [evaluation_step, confusion_matrix], + feed_dict={ + fingerprint_input: test_fingerprints, + ground_truth_input: test_ground_truth, + dropout_prob: 1.0 + }) + batch_size = min(FLAGS.batch_size, set_size - i) + total_accuracy += (test_accuracy * batch_size) / set_size + if total_conf_matrix is None: + total_conf_matrix = conf_matrix + else: + total_conf_matrix += conf_matrix + tf.logging.info('Confusion Matrix:\n %s' % (total_conf_matrix)) + tf.logging.info('Final test accuracy = %.2f%% (N=%d)' % (total_accuracy * 100, + set_size)) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + '--data_url', + type=str, + # pylint: disable=line-too-long + default='http://download.tensorflow.org/data/speech_commands_v0.02.tar.gz', + # pylint: enable=line-too-long + help='Location of speech training data archive on the web.') + parser.add_argument( + '--data_dir', + type=str, + default='./speech_dataset/', + help="""\ + Where to download the speech training data to. + """) + parser.add_argument( + '--background_volume', + type=float, + default=0.1, + help="""\ + How loud the background noise should be, between 0 and 1. + """) + parser.add_argument( + '--background_frequency', + type=float, + default=0.8, + help="""\ + How many of the training samples have background noise mixed in. + """) + parser.add_argument( + '--silence_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be silence. + """) + parser.add_argument( + '--unknown_percentage', + type=float, + default=10.0, + help="""\ + How much of the training data should be unknown words. + """) + parser.add_argument( + '--time_shift_ms', + type=float, + default=100.0, + help="""\ + Range to randomly shift the training audio by in time. + """) + parser.add_argument( + '--testing_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a test set.') + parser.add_argument( + '--validation_percentage', + type=int, + default=10, + help='What percentage of wavs to use as a validation set.') + parser.add_argument( + '--sample_rate', + type=int, + default=16000, + help='Expected sample rate of the wavs',) + parser.add_argument( + '--clip_duration_ms', + type=int, + default=1000, + help='Expected duration in milliseconds of the wavs',) + parser.add_argument( + '--window_size_ms', + type=float, + default=30.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--window_stride_ms', + type=float, + default=10.0, + help='How long each spectrogram timeslice is',) + parser.add_argument( + '--dct_coefficient_count', + type=int, + default=40, + help='How many bins to use for the MFCC fingerprint',) + parser.add_argument( + '--how_many_training_steps', + type=str, + default='15000,3000', + help='How many training loops to run',) + parser.add_argument( + '--eval_step_interval', + type=int, + default=400, + help='How often to evaluate the training results.') + parser.add_argument( + '--learning_rate', + type=str, + default='0.001,0.0001', + help='How large a learning rate to use when training.') + parser.add_argument( + '--batch_size', + type=int, + default=100, + help='How many items to train with at once',) + parser.add_argument( + '--summaries_dir', + type=str, + default='/tmp/retrain_logs', + help='Where to save summary logs for TensorBoard.') + parser.add_argument( + '--wanted_words', + type=str, + default='yes,no,up,down,left,right,on,off,stop,go', + help='Words to use (others will be added to an unknown label)',) + parser.add_argument( + '--train_dir', + type=str, + default='/tmp/speech_commands_train', + help='Directory to write event logs and checkpoint.') + parser.add_argument( + '--save_step_interval', + type=int, + default=100, + help='Save model checkpoint every save_steps.') + parser.add_argument( + '--start_checkpoint', + type=str, + default='', + help='If specified, restore this pretrained model before any training.') + parser.add_argument( + '--model_architecture', + type=str, + default='dnn', + help='What model architecture to use') + parser.add_argument( + '--model_size_info', + type=int, + nargs="+", + default=[128,128,128], + help='Model dimensions - different for various models') + parser.add_argument( + '--check_nans', + type=bool, + default=False, + help='Whether to check for invalid numbers during processing') + + FLAGS, unparsed = parser.parse_known_args() + tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) + diff --git a/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/train_commands.txt b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/train_commands.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e503c00d7340de35511d2f8ad0dea147fdc9b3b --- /dev/null +++ b/TensorFlow/built-in/nlp/DS-CNN_RT2_ID1769_for_TensorFlow/train_commands.txt @@ -0,0 +1,34 @@ +#DNN Models +python train.py --model_architecture dnn --model_size_info 144 144 144 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 40 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/DNN/DNN1/retrain_logs --train_dir work/DNN/DNN1/training +python train.py --model_architecture dnn --model_size_info 256 256 256 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 40 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/DNN/DNN2/retrain_logs --train_dir work/DNN/DNN2/training +python train.py --model_architecture dnn --model_size_info 436 436 436 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 40 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/DNN/DNN3/retrain_logs --train_dir work/DNN/DNN3/training + +#CNN Models +python train.py --model_architecture cnn --model_size_info 28 10 4 1 1 30 10 4 2 1 16 128 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/CNN/CNN1/retrain_logs --train_dir work/CNN/CNN1/training +python train.py --model_architecture cnn --model_size_info 64 10 4 1 1 48 10 4 2 1 16 128 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/CNN/CNN2/retrain_logs --train_dir work/CNN/CNN2/training +python train.py --model_architecture cnn --model_size_info 60 10 4 1 1 76 10 4 2 1 58 128 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/CNN/CNN3/retrain_logs --train_dir work/CNN/CNN3/training + +#Basic LSTM Models +python train.py --model_architecture basic_lstm --model_size_info 118 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/Basic_LSTM/Basic_LSTM1/retrain_logs --train_dir work/Basic_LSTM/Basic_LSTM1/training +python train.py --model_architecture basic_lstm --model_size_info 214 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/Basic_LSTM/Basic_LSTM2/retrain_logs --train_dir work/Basic_LSTM/Basic_LSTM2/training +python train.py --model_architecture basic_lstm --model_size_info 344 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/Basic_LSTM/Basic_LSTM3/retrain_logs --train_dir work/Basic_LSTM/Basic_LSTM3/training + +#LSTM Models +python train.py --model_architecture lstm --model_size_info 98 144 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 40 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/LSTM/LSTM1/retrain_logs --train_dir work/LSTM/LSTM1/training +python train.py --model_architecture lstm --model_size_info 130 280 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/LSTM/LSTM2/retrain_logs --train_dir work/LSTM/LSTM2/training +python train.py --model_architecture lstm --model_size_info 188 500 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/LSTM/LSTM3/retrain_logs --train_dir work/LSTM/LSTM3/training + +#GRU Models +python train.py --model_architecture gru --model_size_info 1 154 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 40 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/GRU/GRU1/retrain_logs --train_dir work/GRU/GRU1/training +python train.py --model_architecture gru --model_size_info 1 250 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/GRU/GRU2/retrain_logs --train_dir work/GRU/GRU2/training +python train.py --model_architecture gru --model_size_info 1 400 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/GRU/GRU3/retrain_logs --train_dir work/GRU/GRU3/training + +#CRNN Models +python train.py --model_architecture crnn --model_size_info 48 10 4 2 2 2 60 84 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/CRNN/CRNN1/retrain_logs --train_dir work/CRNN/CRNN1/training +python train.py --model_architecture crnn --model_size_info 128 10 4 2 2 2 76 164 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/CRNN/CRNN2/retrain_logs --train_dir work/CRNN/CRNN2/training +python train.py --model_architecture crnn --model_size_info 100 10 4 2 1 2 136 188 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/CRNN/CRNN3/retrain_logs --train_dir work/CRNN/CRNN3/training + +#DS-CNN Models +python train.py --model_architecture ds_cnn --model_size_info 5 64 10 4 2 2 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 64 3 3 1 1 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/DS_CNN/DS_CNN1/retrain_logs --train_dir work/DS_CNN/DS_CNN1/training +python train.py --model_architecture ds_cnn --model_size_info 5 172 10 4 2 1 172 3 3 2 2 172 3 3 1 1 172 3 3 1 1 172 3 3 1 1 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/DS_CNN/DS_CNN2/retrain_logs --train_dir work/DS_CNN/DS_CNN2/training +python train.py --model_architecture ds_cnn --model_size_info 6 276 10 4 2 1 276 3 3 2 2 276 3 3 1 1 276 3 3 1 1 276 3 3 1 1 276 3 3 1 1 --dct_coefficient_count 10 --window_size_ms 40 --window_stride_ms 20 --learning_rate 0.0005,0.0001,0.00002 --how_many_training_steps 10000,10000,10000 --summaries_dir work/DS_CNN/DS_CNN3/retrain_logs --train_dir work/DS_CNN/DS_CNN3/training diff --git a/TensorFlow/built-in/nlp/GNMT_ID1819_for_TensorFlow/test/train_RT2_performance_1p.sh b/TensorFlow/built-in/nlp/GNMT_ID1819_for_TensorFlow/test/train_RT2_performance_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..930bda2d8364abdafaf3951f8abaef7c59c22be4 --- /dev/null +++ b/TensorFlow/built-in/nlp/GNMT_ID1819_for_TensorFlow/test/train_RT2_performance_1p.sh @@ -0,0 +1,209 @@ +#!/bin/bash + +#当前路径,不需要修改 +cur_path=`pwd` + +#集合通信参数,不需要修改 + +export RANK_SIZE=1 +export JOB_ID=10087 +RANK_ID_START=0 + +#使能RT2.0 +export ENABLE_RUNTIME_V2=1 + +# 数据集路径,保持为空,不需要修改 +data_path="" + +#基础参数,需要模型审视修改 +#网络名称,同目录名称 +Network="GNMT_ID1819_for_TensorFlow" +#训练epoch +train_epochs=1 +#训练batch_size +batch_size=128 +#训练step +train_steps=50 +#学习率 +learning_rate=0.0005 +#训练模式 +mode="train" +use_DynamicRNN=True +use_fused_lstm=True +use_fused_lstm_dec=False +npu_loss_scale=1 + +#TF2.X独有,需要模型审视修改 +export NPU_LOOP_SIZE=${train_steps} + +#维测参数,precision_mode需要模型审视修改 +precision_mode="allow_mix_precision" +#维持参数,以下不需要修改 +over_dump=False +data_dump_flag=False +data_dump_step="10" +profiling=False + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_performance_1P.sh " + echo " " + echo "parameter explain: + --precision_mode precision mode(allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision) + --over_dump if or not over detection, default is False + --data_dump_flag data dump flag, default is False + --data_dump_step data dump step, default is 10 + --profiling if or not profiling for performance debug, default is False + --data_path source data of training + -h/--help show help message + " + exit 1 +fi + +#参数校验,不需要修改 +for para in $* +do + if [[ $para == --precision_mode* ]];then + precision_mode=`echo ${para#*=}` + elif [[ $para == --over_dump* ]];then + over_dump=`echo ${para#*=}` + over_dump_path=${cur_path}/output/overflow_dump + mkdir -p ${over_dump_path} + elif [[ $para == --data_dump_flag* ]];then + data_dump_flag=`echo ${para#*=}` + data_dump_path=${cur_path}/output/data_dump + mkdir -p ${data_dump_path} + elif [[ $para == --data_dump_step* ]];then + data_dump_step=`echo ${para#*=}` + elif [[ $para == --profiling* ]];then + profiling=`echo ${para#*=}` + profiling_dump_path=${cur_path}/output/profiling + mkdir -p ${profiling_dump_path} + elif [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + elif [[ $para == --train_steps* ]];then + train_steps=`echo ${para#*=}` + elif [[ $para == --learning_rate* ]];then + learning_rate=`echo ${para#*=}` + elif [[ $para == --mode* ]];then + mode=`echo ${para#*=}` + elif [[ $para == --use_DynamicRNN* ]];then + use_DynamicRNN=`echo ${para#*=}` + elif [[ $para == --use_fused_lstm=* ]];then + use_fused_lstm=`echo ${para#*=}` + elif [[ $para == --use_fused_lstm_dec=* ]];then + use_fused_lstm_dec=`echo ${para#*=}` + elif [[ $para == --npu_loss_scale* ]];then + npu_loss_scale=`echo ${para#*=}` + fi +done + +#校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be confing" + exit 1 +fi + +#cp /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json_bak +#num=`grep -n "Reduction" aic-ascend910-ops-info.json | awk '{print $1}' | cut -d ':' -f 1` +#num=`expr $num - 2` +#string="},\"precision_reduce\":{\"flag\":\"false\"}" +#sed -i "${num}c${string}" aic-ascend910-ops-info.json +#mv /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py_bak +#cp ${cur_path}/sigmoid.py /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/ + +#训练开始时间,不需要修改 +start_time=$(date +%s) + +#进入训练脚本目录,需要模型审视修改 +cd $cur_path/.. +for((RANK_ID=$RANK_ID_START;RANK_ID<$((RANK_SIZE+RANK_ID_START));RANK_ID++)); +do + #设置环境变量,不需要修改 + echo "Device ID: $ASCEND_DEVICE_ID" + export RANK_ID=$RANK_ID + + + + #创建DeviceID输出目录,不需要修改 + if [ -d ${cur_path}/output/${ASCEND_DEVICE_ID} ];then + rm -rf ${cur_path}/output/${ASCEND_DEVICE_ID} + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + else + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + fi + + #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 + #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path + nohup python3 nmt.py \ + --mode=${mode} \ + --data_dir=${data_path} \ + --debug_num_train_steps=${train_steps} \ + --max_train_epochs=${train_epochs} \ + --output_dir=${cur_path}/output/$ASCEND_DEVICE_ID/ckpt \ + --learning_rate=${learning_rate} \ + --precision_mode=${precision_mode} \ + --over_dump=${over_dump} \ + --over_dump_path=${over_dump_path} \ + --data_dump_flag=${data_dump_flag} \ + --data_dump_step=${data_dump_step} \ + --data_dump_path=${data_dump_path} \ + --batch_size=${batch_size} \ + --profiling=${profiling} \ + --use_DynamicRNN=${use_DynamicRNN} \ + --use_fused_lstm=${use_fused_lstm} \ + --use_fused_lstm_dec=${use_fused_lstm_dec} \ + --npu_loss_scale=${npu_loss_scale} \ + --profiling_dump_path=${profiling_dump_path} > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & +done +wait + +#训练结束时间,不需要修改 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +#结果打印,不需要修改 +echo "------------------ Final result ------------------" +#输出性能FPS,需要模型审视修改 +time=`grep -r "] loss" $cur_path/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log | awk 'END {print $11}' | cut -d '(' -f 2` +train_time=`echo "$time"|awk '{print $1/10}'` +FPS=`echo "$batch_size $train_time"|awk '{print $1/$2}'` +#打印,不需要修改 +echo "Final Performance images/sec : $FPS" + +#打印,不需要修改 +echo "E2E Training Duration sec : $e2e_time" + +#性能看护结果汇总 +#训练用例信息,不需要修改 +BatchSize=${batch_size} +DeviceType=`uname -m` +CaseName=${Network}_bs${BatchSize}_${RANK_SIZE}'p'_'RT2'_'perf' + +##获取性能数据,不需要修改 +#吞吐量 +ActualFPS=${FPS} +#单迭代训练时长 +TrainingTime=$train_time + +#从train_$ASCEND_DEVICE_ID.log提取Loss到train_${CaseName}_loss.txt中,需要根据模型审视 +grep "] loss" $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk '{print $7}'|cut -d ',' -f 1 > $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt + +#最后一个迭代loss值,不需要修改 +ActualLoss=`awk 'END {print}' $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt` + +#rm -f /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json +#mv /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json_bak /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json +#rm -f /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py +#mv /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py_bak /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${BatchSize}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = ${DeviceType}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${ActualFPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${TrainingTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log diff --git a/TensorFlow/built-in/nlp/GNMT_ID1819_for_TensorFlow/test/train_RT2_performance_8p.sh b/TensorFlow/built-in/nlp/GNMT_ID1819_for_TensorFlow/test/train_RT2_performance_8p.sh new file mode 100644 index 0000000000000000000000000000000000000000..0d5420327ec71d2761386bf7d6f5b38b9413a366 --- /dev/null +++ b/TensorFlow/built-in/nlp/GNMT_ID1819_for_TensorFlow/test/train_RT2_performance_8p.sh @@ -0,0 +1,229 @@ +#!/bin/bash + +#当前路径,不需要修改 +cur_path=`pwd` + +#集合通信参数,不需要修改 +#保证rank table file 文件rank_table_8p.json存放在和test同级的configs目录下 +export RANK_SIZE=8 +export RANK_TABLE_FILE=${cur_path}/../configs/rank_table_8p.json +export JOB_ID=10087 +RANK_ID_START=0 + +#使能RT2.0 +export ENABLE_RUNTIME_V2=1 + +# 数据集路径,保持为空,不需要修改 +data_path="" + +#基础参数 需要模型审视修改 +#网络名称,同目录名称 +Network="GNMT_ID1819_for_TensorFlow" +#训练epoch +train_epochs=6 +#训练batch_size +batch_size=1024 +#训练step +train_steps=1000 +#学习率 +learning_rate=0.002 +#训练模式 +mode="train" +use_DynamicRNN=True +use_fused_lstm=True +use_fused_lstm_dec=False +npu_loss_scale=1 + +#TF2.X独有,需要模型审视修改 +export NPU_LOOP_SIZE=${train_steps} + +#维测参数,precision_mode需要模型审视修改 +precision_mode="allow_mix_precision" +#维持参数,以下不需要修改 +over_dump=False +data_dump_flag=False +data_dump_step="10" +profiling=False + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_performance_8P_256bs_SGD.sh " + echo " " + echo "parameter explain: + --precision_mode precision mode(allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision) + --over_dump if or not over detection, default is False + --data_dump_flag data dump flag, default is 0 + --data_dump_step data dump step, default is 10 + --profiling if or not profiling for performance debug, default is False + --data_path source data of training + -h/--help show help message + " + exit 1 +fi + +#参数校验,不需要修改 +for para in $* +do + if [[ $para == --precision_mode* ]];then + precision_mode=`echo ${para#*=}` + elif [[ $para == --over_dump* ]];then + over_dump=`echo ${para#*=}` + over_dump_path=${cur_path}/output/overflow_dump + mkdir -p ${over_dump_path} + elif [[ $para == --data_dump_flag* ]];then + data_dump_flag=`echo ${para#*=}` + data_dump_path=${cur_path}/output/data_dump + mkdir -p ${data_dump_path} + elif [[ $para == --data_dump_step* ]];then + data_dump_step=`echo ${para#*=}` + elif [[ $para == --profiling* ]];then + profiling=`echo ${para#*=}` + profiling_dump_path=${cur_path}/output/profiling + mkdir -p ${profiling_dump_path} + elif [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + elif [[ $para == --bind_core* ]]; then + bind_core=`echo ${para#*=}` + name_bind="_bindcore" + elif [[ $para == --train_steps* ]];then + train_steps=`echo ${para#*=}` + elif [[ $para == --learning_rate* ]];then + learning_rate=`echo ${para#*=}` + elif [[ $para == --mode* ]];then + mode=`echo ${para#*=}` + elif [[ $para == --use_DynamicRNN* ]];then + use_DynamicRNN=`echo ${para#*=}` + elif [[ $para == --use_fused_lstm=* ]];then + use_fused_lstm=`echo ${para#*=}` + elif [[ $para == --use_fused_lstm_dec=* ]];then + use_fused_lstm_dec=`echo ${para#*=}` + elif [[ $para == --npu_loss_scale* ]];then + npu_loss_scale=`echo ${para#*=}` + fi +done + +#校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be confing" + exit 1 +fi + +#cp /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json_bak +#num=`grep -n "Reduction" aic-ascend910-ops-info.json | awk '{print $1}' | cut -d ':' -f 1` +#num=`expr $num - 2` +#string="},\"precision_reduce\":{\"flag\":\"false\"}" +#sed -i "${num}c${string}" aic-ascend910-ops-info.json +#mv /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py_bak +#cp ${cur_path}/sigmoid.py /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/ + +#训练开始时间,不需要修改 +start_time=$(date +%s) + +#执行训练,需要模型审视修改 +cd $cur_path/.. +for((RANK_ID=$RANK_ID_START;RANK_ID<$((RANK_SIZE+RANK_ID_START));RANK_ID++)); +do + #设置环境变量,不需要修改 + echo "Device ID: $RANK_ID" + export RANK_ID=$RANK_ID + export ASCEND_DEVICE_ID=$RANK_ID + ASCEND_DEVICE_ID=$RANK_ID + + #创建DeviceID输出目录,不需要修改 + if [ -d ${cur_path}/output/${ASCEND_DEVICE_ID} ];then + rm -rf ${cur_path}/output/${ASCEND_DEVICE_ID} + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + else + mkdir -p ${cur_path}/output/$ASCEND_DEVICE_ID/ckpt + fi + + #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 + #--data_dir, --model_dir, --precision_mode, --over_dump, --over_dump_path,--data_dump_flag,--data_dump_step,--data_dump_path,--profiling,--profiling_dump_path + corenum=`cat /proc/cpuinfo |grep 'processor' |wc -l` + let a=RANK_ID*${corenum}/8 + let b=RANK_ID+1 + let c=b*${corenum}/8-1 + if [ "x${bind_core}" != x ];then + bind_core="taskset -c $a-$c" + fi + nohup ${bind_core} python3 nmt.py \ + --mode=${mode} \ + --data_dir=${data_path} \ + --debug_num_train_steps=${train_steps} \ + --max_train_epochs=${train_epochs} \ + --output_dir=${cur_path}/output/$ASCEND_DEVICE_ID/ckpt \ + --learning_rate=${learning_rate} \ + --precision_mode=${precision_mode} \ + --over_dump=${over_dump} \ + --over_dump_path=${over_dump_path} \ + --data_dump_flag=${data_dump_flag} \ + --data_dump_step=${data_dump_step} \ + --data_dump_path=${data_dump_path} \ + --batch_size=${batch_size} \ + --profiling=${profiling} \ + --use_DynamicRNN=${use_DynamicRNN} \ + --use_fused_lstm=${use_fused_lstm} \ + --use_fused_lstm_dec=${use_fused_lstm_dec} \ + --npu_loss_scale=${npu_loss_scale} \ + --profiling_dump_path=${profiling_dump_path} > ${cur_path}/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 & +done +wait + +#训练结束时间,不需要修改 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +#结果打印,不需要修改 +echo "------------------ Final result ------------------" +#输出性能FPS,需要模型审视修改 +time=(`grep -r "] loss" $cur_path/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log | awk -F '(' '{print $2}' | awk '{print $1}'`) +for((i=0;i<${#time[*]};i++)) +do + if [ `echo "${time[i]}"|awk '{if($1<10) {print 0} else {print 1}}'` -eq 0 ] + then + step_time=`echo "${time[i]}"|awk '{print $1*1000}'` + sum=`echo "$sum $step_time"|awk '{print $1+$2}'` + count=`expr $count + 1` + fi +done +train_time=`echo "$sum $count"|awk '{print $1/$2}'` +FPS=`echo "$batch_size $train_time"|awk '{print $1*1000/$2}'` +#打印,不需要修改 +echo "Final Performance images/sec : $FPS" + +#打印,不需要修改 +echo "E2E Training Duration sec : $e2e_time" + +#性能看护结果汇总 +#训练用例信息,不需要修改 +BatchSize=${batch_size} +DeviceType=`uname -m` +CaseName=${Network}${name_bind}_bs${BatchSize}_${RANK_SIZE}'p'_'RT2'_'perf' + +##获取性能数据,不需要修改 +#吞吐量 +ActualFPS=${FPS} +#单迭代训练时长 +TrainingTime=$train_time + +#从train_$ASCEND_DEVICE_ID.log提取Loss到train_${CaseName}_loss.txt中,需要根据模型审视 +grep "] loss" $cur_path/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk '{print $7}'|cut -d ',' -f 1 >> $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt + +#最后一个迭代loss值,不需要修改 +ActualLoss=`awk 'END {print}' $cur_path/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt` + +#rm -f /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json +#mv /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json_bak /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json +#rm -f /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py +#mv /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py_bak /usr/local/Ascend/opp/op_impl/built-in/ai_core/tbe/impl/sigmoid.py + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RANK_SIZE = ${RANK_SIZE}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${BatchSize}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = ${DeviceType}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${ActualFPS}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${TrainingTime}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/output/$ASCEND_DEVICE_ID/${CaseName}.log diff --git a/TensorFlow/contrib/cv/StarGAN_ID1472_for_TensorFlow/test/train_RT2_performance_1p.sh b/TensorFlow/contrib/cv/StarGAN_ID1472_for_TensorFlow/test/train_RT2_performance_1p.sh new file mode 100644 index 0000000000000000000000000000000000000000..60bc0a313a6452b31ecc4be95800694d045be2eb --- /dev/null +++ b/TensorFlow/contrib/cv/StarGAN_ID1472_for_TensorFlow/test/train_RT2_performance_1p.sh @@ -0,0 +1,178 @@ +#!/bin/bash + +#当前路径,不需要修改 +cur_path=`pwd`/../ + +#集合通信参数,不需要修改 + +export RANK_SIZE=1 +export JOB_ID=10087 +RANK_ID_START=0 + +#使能RT2.0 +export ENABLE_RUNTIME_V2=1 + +# 数据集路径,保持为空,不需要修改 +data_path='' +ckpt_path='' + +#设置默认日志级别,不需要修改 +export ASCEND_GLOBAL_LOG_LEVEL=3 +#export ASCEND_DEVICE_ID=3 + +#基础参数,需要模型审视修改 +#网络名称,同目录名称 +Network="StarGAN_ID1472_for_TensorFlow" +#训练epoch +train_epochs= +#训练batch_size +batch_size=16 +#训练step +train_steps= +#学习率 +learning_rate= + +#维测参数,precision_mode需要模型审视修改 +precision_mode="allow_mix_precision" +#维持参数,以下不需要修改 +over_dump=False +data_dump_flag=False +data_dump_step="10" +profiling=False + +# 帮助信息,不需要修改 +if [[ $1 == --help || $1 == -h ]];then + echo"usage:./train_performance_1p.sh " + echo " " + echo "parameter explain: + --precision_mode precision mode(allow_fp32_to_fp16/force_fp16/must_keep_origin_dtype/allow_mix_precision) + --over_dump if or not over detection, default is False + --data_dump_flag data dump flag, default is False + --data_dump_step data dump step, default is 10 + --profiling if or not profiling for performance debug, default is False + --data_path source data of training + -h/--help show help message + " + exit 1 +fi + +#参数校验,不需要修改 +for para in $* +do + if [[ $para == --precision_mode* ]];then + precision_mode=`echo ${para#*=}` + elif [[ $para == --over_dump* ]];then + over_dump=`echo ${para#*=}` + over_dump_path=${cur_path}/test/output/overflow_dump + mkdir -p ${over_dump_path} + elif [[ $para == --data_dump_flag* ]];then + data_dump_flag=`echo ${para#*=}` + data_dump_path=${cur_path}/test/output/data_dump + mkdir -p ${data_dump_path} + elif [[ $para == --data_dump_step* ]];then + data_dump_step=`echo ${para#*=}` + elif [[ $para == --profiling* ]];then + profiling=`echo ${para#*=}` + profiling_dump_path=${cur_path}/test/output/profiling + mkdir -p ${profiling_dump_path} + elif [[ $para == --data_path* ]];then + data_path=`echo ${para#*=}` + + elif [[ $para == --ckpt_path* ]];then + ckpt_path=`echo ${para#*=}` + fi +done + +#校验是否传入data_path,不需要修改 +if [[ $data_path == "" ]];then + echo "[Error] para \"data_path\" must be confing" + exit 1 + +fi + +#训练开始时间,不需要修改 +start_time=$(date +%s) + +#进入训练脚本目录,需要模型审视修改 +cd $cur_path/ +for((RANK_ID=$RANK_ID_START;RANK_ID<$((RANK_SIZE+RANK_ID_START));RANK_ID++)); +do + #设置环境变量,不需要修改 + echo "Device ID: $ASCEND_DEVICE_ID" + export RANK_ID=$RANK_ID + + + + #创建DeviceID输出目录,不需要修改 + if [ -d ${cur_path}/test/output/${ASCEND_DEVICE_ID} ];then + rm -rf ${cur_path}/test/output/${ASCEND_DEVICE_ID} + mkdir -p ${cur_path}/test/output/$ASCEND_DEVICE_ID/ckpt + else + mkdir -p ${cur_path}/test/output/$ASCEND_DEVICE_ID/ckpt + fi + + + + + # 绑核,不需要的绑核的模型删除,需要的模型审视修改 + let a=RANK_ID*12 + let b=RANK_ID+1 + let c=b*12-1 + + + #执行训练脚本,以下传参不需要修改,其他需要模型审视修改 + python3 main.py --phase=train \ + --image_root=${data_path}/CelebA/Img/img_align_celeba/ \ + --metadata_path=${data_path}/CelebA/Anno/list_attr_celeba.txt \ + --batch_size=16 \ + --c_dim=5 \ + --selected_attrs="Black_Hair Blond_Hair Brown_Hair Male Young" \ + --training_iterations=2000 \ + --lr_update_step=10 \ + --num_step_decay=1000 \ + --output_dir=./logs/ \ + --summary_steps=10 \ + --save_steps=10 \ + --checkpoint_steps=10000 > ${cur_path}test/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log 2>&1 + + +done +wait + +#训练结束时间,不需要修改 +end_time=$(date +%s) +e2e_time=$(( $end_time - $start_time )) + +#结果打印,不需要修改 +echo "------------------ Final result ------------------" +#输出性能FPS,需要模型审视修改 +TrainingTime=`grep "Perf:" $cur_path/test/output/${ASCEND_DEVICE_ID}/train_${ASCEND_DEVICE_ID}.log |awk -F 'Perf:' '{print $2}'|awk 'END {print $1}'` + + +#性能看护结果汇总 +#训练用例信息,不需要修改 +BatchSize=${batch_size} +DeviceType=`uname -m` +CaseName=${Network}_bs${BatchSize}_${RANK_SIZE}'p'_'RT2'_'perf' + +##获取性能数据,不需要修改 +#吞吐量 +ActualFPS=`awk 'BEGIN{printf "%.2f\n", '${batch_size}'/'${TrainingTime}'}'` + +#从train_$ASCEND_DEVICE_ID.log提取Loss到train_${CaseName}_loss.txt中,需要根据模型审视 +grep 'G/loss_rec:' $cur_path/test/output/$ASCEND_DEVICE_ID/train_$ASCEND_DEVICE_ID.log|awk -F 'G/loss_rec:' '{print $2}'|awk '{print $1}' > $cur_path/test/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt + +#最后一个迭代loss值,不需要修改 +ActualLoss=`awk 'END {print}' $cur_path/test/output/$ASCEND_DEVICE_ID/train_${CaseName}_loss.txt` + +#关键信息打印到${CaseName}.log中,不需要修改 +echo "Network = ${Network}" > $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "RankSize = ${RANK_SIZE}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "BatchSize = ${BatchSize}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "DeviceType = ${DeviceType}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "CaseName = ${CaseName}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualFPS = ${ActualFPS}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainingTime = ${TrainingTime}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "ActualLoss = ${ActualLoss}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "TrainAccuracy = None" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log +echo "E2ETrainingTime = ${e2e_time}" >> $cur_path/test/output/$ASCEND_DEVICE_ID/${CaseName}.log