diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..ec490a0e6e38d9514a9fb1ee3b0c01582fb31fea --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +__pycache__ +pose_env_1 +testing +vit_env +vit_test +test_vit_model.ipynb +models +models_2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d471d5f5779817d1664e401d16ed6888dca4c66f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__ +pose_env_1 +testing +vit_env +test_vit_model.ipynb diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..2ec049923495379bc15a3625571cb0dca722261c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.10 + +WORKDIR /app + +COPY requirements.txt . + +RUN apt-get update && apt-get install ffmpeg libsm6 libxext6 -y +RUN pip install --upgrade pip + +# --no-cache-dir +RUN pip install -r requirements.txt + +COPY . . + +EXPOSE 7860 + +ENV GRADIO_SERVER_NAME="0.0.0.0" +ENV USE_NNPACK=0 +CMD ["python", "app.py"] \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..88d645569ab8b11bd7fe96fc2e3bcc942af13b47 --- /dev/null +++ b/app.py @@ -0,0 +1,117 @@ +import gradio as gr +from main_func import video_identity + +with gr.Blocks() as demo: + + with gr.Row(variant='compact'): + + with gr.Column(): + gr.Markdown("#### Dynamic Time Warping:") + + with gr.Row(variant='compact'): + dtw_mean = gr.Slider( + value=0.5, + minimum=0, + maximum=1.0, + step=0.05, + label="Winsorize Mean" + ) + + dtw_filter = gr.Slider( + value=3, + minimum=1, + maximum=20, + step=1, + label="Savitzky-Golay Filter" + ) + + gr.Markdown("#### Thresholds:") + + with gr.Row(variant='compact'): + angles_sensitive = gr.Number( + value=15, + minimum=0, + maximum=75, + step=1, + min_width=100, + label="Sensitive" + ) + + angles_common = gr.Number( + value=25, + minimum=0, + maximum=75, + step=1, + min_width=100, + label="Standart" + ) + + angles_insensitive = gr.Number( + value=45, + minimum=0, + maximum=75, + step=1, + min_width=100, + label="Insensitive" + ) + + gr.Markdown("#### Patience:") + + trigger_state = gr.Radio(value="three", choices=["three", "two"], label="Trigger Count") + + input_teacher = gr.Video(show_share_button=False, show_download_button=False, sources=["upload"], label="Teacher's Video") + input_student = gr.Video(show_share_button=False, show_download_button=False, sources=["upload"], label="Student's Video") + + + with gr.Accordion("Clarifications:", open=True): + with gr.Accordion("Dynamic Time Warping:", open=False): + gr.Markdown(""" + Dynamic Time Warping is an algorithm that performs frame-by-frame alignment for videos with different speeds. + + - **Winsorized mean**: Determines the portion of DTW paths, sorted from best to worst, to use for generating the mean DTW alignment. Reasonable values range from 0.25 to 0.6. + - **Savitzky-Golay Filter**: Enhances the capabilities of the Winsorized mean, making DTW alignment more similar to a strict line. Reasonable values range from 2 to 10. + """) + + with gr.Accordion("Thresholds:", open=False): + gr.Markdown(""" + Thresholds are used to identify student errors in dance. If the difference in angle between the teacher's and student's videos exceeds this threshold, it is counted as an error. + + - **Sensitive**: A threshold that is currently not used. + - **Standard**: A threshold for most angles. Reasonable values range from 20 to 40. + - **Insensitive**: A threshold for difficult areas, such as hands and toes. Reasonable values range from 35 to 55. + """) + + with gr.Accordion("Patience:", open=False): + gr.Markdown(""" + Patience helps prevent model errors by highlighting only errors detected in consecutive frames. + + - **Three**: Utilizes 3 consecutive frames for error detection. + - **Two**: Utilizes 2 consecutive frames for error detection. + + Both options can be used interchangeably. + """) + + + + with gr.Row(): + gr_button = gr.Button("Run Pose Comparison") + + with gr.Row(): + gr.HTML("
") + + + with gr.Row(): + output_merged = gr.Video(show_download_button=True) + + with gr.Row(): + general_log = gr.TextArea(lines=10, max_lines=9999, label="Error log") + + gr_button.click( + fn=video_identity, + inputs=[dtw_mean, dtw_filter, angles_sensitive, angles_common, angles_insensitive, trigger_state, input_teacher, input_student], + outputs=[output_merged, general_log] + ) + + +if __name__ == "__main__": + demo.launch() \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000000000000000000000000000000000000..dd38c8dff3f023a68b89af0b45deb882d8c2ab39 --- /dev/null +++ b/config.py @@ -0,0 +1,373 @@ +CONNECTIONS_VIT_FULL = [ + # head + (0, 2), + (0, 1), + (2, 4), + (1, 3), + (0, 6), + (0, 5), + + # right arm + (6, 8), + (8, 10), + + # right hand + (10, 112), + + # Big toe 1 + (112, 113), + (113, 114), + (114, 115), + (115, 116), + + # toe 2 + (112, 117), + (117, 118), + (118, 119), + (119, 120), + + # toe 3 + (112, 121), + (121, 122), + (122, 123), + (123, 124), + + # toe 4 + (112, 125), + (125, 126), + (126, 127), + (127, 128), + + # toe 5 + (112, 129), + (129, 130), + (130, 131), + (131, 132), + + + + # left arm + (5, 7), + (7, 9), + + # left hand + (9, 91), + + + # Big toe 1 + (91, 92), + (92, 93), + (93, 94), + (94, 95), + + # toe 2 + (91, 96), + (96, 97), + (97, 98), + (98, 99), + + # toe 3 + (91, 100), + (100, 101), + (101, 102), + (102, 103), + + # toe 4 + (91, 104), + (104, 105), + (105, 106), + (106, 107), + + # toe 5 + (91, 108), + (108, 109), + (109, 110), + (110, 111), + + + + # torso + (6, 5), + (12, 11), + (6, 12), + (5, 11), + + # right leg + (12, 14), + (14, 16), + + # right foot + (16, 22), + (22, 21), + (22, 20), + + + # left leg + (11, 13), + (13, 15), + + # left foot + (15, 19), + (19, 18), + (19, 17), +] + +EDGE_GROUPS_FOR_ERRORS = [ + [0, 2, 4], + [0, 1, 3], + + # neck + [6, 0, 2], + [5, 0, 1], + + # right arm + + # right shoulder + [5, 6, 8], + + # right elbow + [6, 8, 10], + + # right hand + [8, 10, 121], + + [112, 114, 116], + [112, 117, 120], + [112, 121, 124], + [112, 125, 128], + [112, 129, 132], + + # left arm + + # left shoulder + [6, 5, 7], + + # left elbow + [5, 7, 9], + + # left hand + [7, 9, 100], + + [91, 93, 95], + [91, 96, 99], + [91, 100, 103], + [91, 104, 107], + [91, 108, 111], + + + # right leg + + # right upper-leg + [6, 12, 14], + + # right middle-leg + [12, 14, 16], + + # right lower-leg + [14, 16, 22], + [16, 22, 21], + [16, 22, 20], + + # left leg + + # left upper-leg + [5, 11, 13], + + # left middle-leg + [11, 13, 15], + + # left lower-leg + [13, 15, 19], + [15, 19, 17], + [15, 19, 18], + +] + + + +CONNECTIONS_FOR_ERROR = [ + # head + (0, 2), + (2, 4), + (0, 1), + (1, 3), + + # right arm + (6, 0), + (8, 6), + (10, 8), + + # right hand + # (121, 10), + + (112, 114), + (114, 116), + + (112, 117), + (117, 120), + + (112, 121), + (121, 124), + + (112, 125), + (125, 128), + + (112, 129), + (129, 132), + + # left arm + (5, 0), + (7, 5), + (9, 7), + + # left hand + # (100, 9), + + (91, 93), + (93, 95), + + (91, 96), + (96, 99), + + (91, 100), + (100, 103), + + (91, 104), + (104, 107), + + (91, 108), + (108, 111), + + # torso + (6, 12), + (5, 11), + + # right leg + (12, 14), + (14, 16), + + (16, 22), + (22, 21), + (22, 20), + + # left leg + (11, 13), + (13, 15), + + (15, 19), + (19, 17), + (19, 18), + +] + +def get_thresholds(sensetive_error, general_error, unsensetive_error): + thresholds = [ + general_error, + general_error, + general_error, + general_error, + + general_error, + general_error, + + unsensetive_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + + general_error, + general_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + + general_error, + general_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + + general_error, + general_error, + unsensetive_error, + unsensetive_error, + unsensetive_error, + ] + + return thresholds + + +EDGE_GROUPS_FOR_SUMMARY = { + (2, 4): "Head position is incorrect", + (1, 3): "Head position is incorrect", + + # neck + + (0, 2): "Head position is incorrect", + (0, 1): "Head position is incorrect", + + # right arm + + # right shoulder + (6, 8): "Right shoulder position is incorrect", + + # right elbow + (8, 10): "Right elbow position is incorrect", + + # right hand + (10, 121): "Right hand's palm position is incorrect", + + (114, 116): "Right thumb finger position is incorrect", + (117, 120): "Right index finger position is incorrect", + (121, 124): "Right middle finger position is incorrect", + (125, 128): "Right ring finger position is incorrect", + (129, 132): "Right pinky finger position is incorrect", + + # left arm + + # left shoulder + (5, 7): "Left shoulder position is incorrect", + + # left elbow + (7, 9): "Left elbow position is incorrect", + + # left hand + (9, 100): "Left hand palm position is incorrect", + + (93, 95): "Left thumb finger position is incorrect", + (96, 99): "Left index finger position is incorrect", + (100, 103): "Left middle finger position is incorrect", + (104, 107): "Left ring finger position is incorrect", + (108, 111): "Left pinky finger position is incorrect", + + # right leg + + # right upper-leg + (12, 14): "Right thigh position is incorrect", + + # right middle-leg + (14, 16): "Right shin position is incorrect", + + # right lower-leg + (16, 22): "Right foot position is incorrect", + (22, 21): "Right shin position is incorrect", + (22, 20): "Right shin position is incorrect", + + # left leg + + # left upper-leg + (11, 13): "Left thigh position is incorrect", + + # left middle-leg + (13, 15): "Left shin position is incorrect", + + # left lower-leg + (15, 19): "Left foot position is incorrect", + (19, 17): "Left shin position is incorrect", + (19, 18): "Left shin position is incorrect" +} diff --git a/easy_ViTPose/__init__.py b/easy_ViTPose/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b1d8b1d2065b72203c2421478c1d933d7c5e0c0a --- /dev/null +++ b/easy_ViTPose/__init__.py @@ -0,0 +1,5 @@ +from .inference import VitInference + +__all__ = [ + 'VitInference' +] diff --git a/easy_ViTPose/config.yaml b/easy_ViTPose/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..948d55fd61f80b44b004269938b00e7589aa54dc --- /dev/null +++ b/easy_ViTPose/config.yaml @@ -0,0 +1,14 @@ +# Train config --------------------------------------- +log_level: logging.INFO +seed: 0 +deterministic: True +cudnn_benchmark: True # Use cudnn +resume_from: "ckpts/og-vitpose-s.pth" # CKPT path +# resume_from: False +gpu_ids: [0] +launcher: 'none' # When distributed training ['none', 'pytorch', 'slurm', 'mpi'] +use_amp: True +validate: True +autoscale_lr: False +dist_params: + ... diff --git a/easy_ViTPose/configs/ViTPose_aic.py b/easy_ViTPose/configs/ViTPose_aic.py new file mode 100644 index 0000000000000000000000000000000000000000..924e48668ec8cfbf8f4c2c0611b1d7059fa573bd --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_aic.py @@ -0,0 +1,20 @@ +from .ViTPose_common import * + +# Channel configuration +channel_cfg = dict( + num_output_channels=14, + dataset_joints=14, + dataset_channel=[ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], + ], + inference_channel=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]) + +# Set models channels +data_cfg['num_output_channels'] = channel_cfg['num_output_channels'] +data_cfg['num_joints']= channel_cfg['dataset_joints'] +data_cfg['dataset_channel']= channel_cfg['dataset_channel'] +data_cfg['inference_channel']= channel_cfg['inference_channel'] + +names = ['small', 'base', 'large', 'huge'] +for name in names: + globals()[f'model_{name}']['keypoint_head']['out_channels'] = channel_cfg['num_output_channels'] diff --git a/easy_ViTPose/configs/ViTPose_ap10k.py b/easy_ViTPose/configs/ViTPose_ap10k.py new file mode 100644 index 0000000000000000000000000000000000000000..37202d407a6fdb07d30875756007f1afebd60437 --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_ap10k.py @@ -0,0 +1,22 @@ +from .ViTPose_common import * + +# Channel configuration +channel_cfg = dict( + num_output_channels=17, + dataset_joints=17, + dataset_channel=[ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + ], + inference_channel=[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + ]) + +# Set models channels +data_cfg['num_output_channels'] = channel_cfg['num_output_channels'] +data_cfg['num_joints']= channel_cfg['dataset_joints'] +data_cfg['dataset_channel']= channel_cfg['dataset_channel'] +data_cfg['inference_channel']= channel_cfg['inference_channel'] + +names = ['small', 'base', 'large', 'huge'] +for name in names: + globals()[f'model_{name}']['keypoint_head']['out_channels'] = channel_cfg['num_output_channels'] diff --git a/easy_ViTPose/configs/ViTPose_apt36k.py b/easy_ViTPose/configs/ViTPose_apt36k.py new file mode 100644 index 0000000000000000000000000000000000000000..37202d407a6fdb07d30875756007f1afebd60437 --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_apt36k.py @@ -0,0 +1,22 @@ +from .ViTPose_common import * + +# Channel configuration +channel_cfg = dict( + num_output_channels=17, + dataset_joints=17, + dataset_channel=[ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + ], + inference_channel=[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 + ]) + +# Set models channels +data_cfg['num_output_channels'] = channel_cfg['num_output_channels'] +data_cfg['num_joints']= channel_cfg['dataset_joints'] +data_cfg['dataset_channel']= channel_cfg['dataset_channel'] +data_cfg['inference_channel']= channel_cfg['inference_channel'] + +names = ['small', 'base', 'large', 'huge'] +for name in names: + globals()[f'model_{name}']['keypoint_head']['out_channels'] = channel_cfg['num_output_channels'] diff --git a/easy_ViTPose/configs/ViTPose_coco.py b/easy_ViTPose/configs/ViTPose_coco.py new file mode 100644 index 0000000000000000000000000000000000000000..ed1ac7376207566198ab0d24b5c66304822304d4 --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_coco.py @@ -0,0 +1,18 @@ +from .ViTPose_common import * + +# Channel configuration +channel_cfg = dict( + num_output_channels=17, + dataset_joints=17, + dataset_channel=list(range(17)), + inference_channel=list(range(17))) + +# Set models channels +data_cfg['num_output_channels'] = channel_cfg['num_output_channels'] +data_cfg['num_joints']= channel_cfg['dataset_joints'] +data_cfg['dataset_channel']= channel_cfg['dataset_channel'] +data_cfg['inference_channel']= channel_cfg['inference_channel'] + +names = ['small', 'base', 'large', 'huge'] +for name in names: + globals()[f'model_{name}']['keypoint_head']['out_channels'] = channel_cfg['num_output_channels'] diff --git a/easy_ViTPose/configs/ViTPose_coco_25.py b/easy_ViTPose/configs/ViTPose_coco_25.py new file mode 100644 index 0000000000000000000000000000000000000000..c1c26a97d65a868258bae49e22e0d27cb75af2a8 --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_coco_25.py @@ -0,0 +1,20 @@ +from .ViTPose_common import * + +# Channel configuration +channel_cfg = dict( + num_output_channels=25, + dataset_joints=25, + dataset_channel=[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24], ], + inference_channel=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24]) + +# Set models channels +data_cfg['num_output_channels'] = channel_cfg['num_output_channels'] +data_cfg['num_joints']= channel_cfg['dataset_joints'] +data_cfg['dataset_channel']= channel_cfg['dataset_channel'] +data_cfg['inference_channel']= channel_cfg['inference_channel'] + +names = ['small', 'base', 'large', 'huge'] +for name in names: + globals()[f'model_{name}']['keypoint_head']['out_channels'] = channel_cfg['num_output_channels'] diff --git a/easy_ViTPose/configs/ViTPose_common.py b/easy_ViTPose/configs/ViTPose_common.py new file mode 100644 index 0000000000000000000000000000000000000000..2207116f638a46a3146ba474706e027461ebe989 --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_common.py @@ -0,0 +1,195 @@ +# Common configuration +optimizer = dict(type='AdamW', lr=1e-3, betas=(0.9, 0.999), weight_decay=0.1, + constructor='LayerDecayOptimizerConstructor', + paramwise_cfg=dict( + num_layers=12, + layer_decay_rate=1 - 2e-4, + custom_keys={ + 'bias': dict(decay_multi=0.), + 'pos_embed': dict(decay_mult=0.), + 'relative_position_bias_table': dict(decay_mult=0.), + 'norm': dict(decay_mult=0.) + } + ) + ) + +optimizer_config = dict(grad_clip=dict(max_norm=1., norm_type=2)) + +# learning policy +lr_config = dict( + policy='step', + warmup='linear', + warmup_iters=300, + warmup_ratio=0.001, + step=[3]) + +total_epochs = 4 +target_type = 'GaussianHeatmap' + +data_cfg = dict( + image_size=[192, 256], + heatmap_size=[48, 64], + soft_nms=False, + nms_thr=1.0, + oks_thr=0.9, + vis_thr=0.2, + use_gt_bbox=False, + det_bbox_thr=0.0, + bbox_file='data/coco/person_detection_results/' + 'COCO_val2017_detections_AP_H_56_person.json', +) + +data_root = '/home/adryw/dataset/COCO17' +data = dict( + samples_per_gpu=64, + workers_per_gpu=6, + val_dataloader=dict(samples_per_gpu=128), + test_dataloader=dict(samples_per_gpu=128), + train=dict( + type='TopDownCocoDataset', + ann_file=f'{data_root}/annotations/person_keypoints_train2017.json', + img_prefix=f'{data_root}/train2017/', + data_cfg=data_cfg), + val=dict( + type='TopDownCocoDataset', + ann_file=f'{data_root}/annotations/person_keypoints_val2017.json', + img_prefix=f'{data_root}/val2017/', + data_cfg=data_cfg), + test=dict( + type='TopDownCocoDataset', + ann_file=f'{data_root}/annotations/person_keypoints_val2017.json', + img_prefix=f'{data_root}/val2017/', + data_cfg=data_cfg) +) + +model_small = dict( + type='TopDown', + pretrained=None, + backbone=dict( + type='ViT', + img_size=(256, 192), + patch_size=16, + embed_dim=384, + depth=12, + num_heads=12, + ratio=1, + use_checkpoint=False, + mlp_ratio=4, + qkv_bias=True, + drop_path_rate=0.1, + ), + keypoint_head=dict( + type='TopdownHeatmapSimpleHead', + in_channels=384, + num_deconv_layers=2, + num_deconv_filters=(256, 256), + num_deconv_kernels=(4, 4), + extra=dict(final_conv_kernel=1, ), + loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)), + train_cfg=dict(), + test_cfg=dict( + flip_test=True, + post_process='default', + shift_heatmap=False, + target_type=target_type, + modulate_kernel=11, + use_udp=True)) + +model_base = dict( + type='TopDown', + pretrained=None, + backbone=dict( + type='ViT', + img_size=(256, 192), + patch_size=16, + embed_dim=768, + depth=12, + num_heads=12, + ratio=1, + use_checkpoint=False, + mlp_ratio=4, + qkv_bias=True, + drop_path_rate=0.3, + ), + keypoint_head=dict( + type='TopdownHeatmapSimpleHead', + in_channels=768, + num_deconv_layers=2, + num_deconv_filters=(256, 256), + num_deconv_kernels=(4, 4), + extra=dict(final_conv_kernel=1, ), + loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)), + train_cfg=dict(), + test_cfg=dict( + flip_test=True, + post_process='default', + shift_heatmap=False, + target_type=target_type, + modulate_kernel=11, + use_udp=True)) + +model_large = dict( + type='TopDown', + pretrained=None, + backbone=dict( + type='ViT', + img_size=(256, 192), + patch_size=16, + embed_dim=1024, + depth=24, + num_heads=16, + ratio=1, + use_checkpoint=False, + mlp_ratio=4, + qkv_bias=True, + drop_path_rate=0.5, + ), + keypoint_head=dict( + type='TopdownHeatmapSimpleHead', + in_channels=1024, + num_deconv_layers=2, + num_deconv_filters=(256, 256), + num_deconv_kernels=(4, 4), + extra=dict(final_conv_kernel=1, ), + loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)), + train_cfg=dict(), + test_cfg=dict( + flip_test=True, + post_process='default', + shift_heatmap=False, + target_type=target_type, + modulate_kernel=11, + use_udp=True)) + +model_huge = dict( + type='TopDown', + pretrained=None, + backbone=dict( + type='ViT', + img_size=(256, 192), + patch_size=16, + embed_dim=1280, + depth=32, + num_heads=16, + ratio=1, + use_checkpoint=False, + mlp_ratio=4, + qkv_bias=True, + drop_path_rate=0.55, + ), + keypoint_head=dict( + type='TopdownHeatmapSimpleHead', + in_channels=1280, + num_deconv_layers=2, + num_deconv_filters=(256, 256), + num_deconv_kernels=(4, 4), + extra=dict(final_conv_kernel=1, ), + loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)), + train_cfg=dict(), + test_cfg=dict( + flip_test=True, + post_process='default', + shift_heatmap=False, + target_type=target_type, + modulate_kernel=11, + use_udp=True)) diff --git a/easy_ViTPose/configs/ViTPose_mpii.py b/easy_ViTPose/configs/ViTPose_mpii.py new file mode 100644 index 0000000000000000000000000000000000000000..2ef2057c84d4cc25af040b4ebb5d6968aabc1e8f --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_mpii.py @@ -0,0 +1,18 @@ +from .ViTPose_common import * + +# Channel configuration +channel_cfg = dict( + num_output_channels=16, + dataset_joints=16, + dataset_channel=list(range(16)), + inference_channel=list(range(16))) + +# Set models channels +data_cfg['num_output_channels'] = channel_cfg['num_output_channels'] +data_cfg['num_joints']= channel_cfg['dataset_joints'] +data_cfg['dataset_channel']= channel_cfg['dataset_channel'] +data_cfg['inference_channel']= channel_cfg['inference_channel'] + +names = ['small', 'base', 'large', 'huge'] +for name in names: + globals()[f'model_{name}']['keypoint_head']['out_channels'] = channel_cfg['num_output_channels'] diff --git a/easy_ViTPose/configs/ViTPose_wholebody.py b/easy_ViTPose/configs/ViTPose_wholebody.py new file mode 100644 index 0000000000000000000000000000000000000000..fb3a1b654b8c73c6297f5ba78c80cb5650b60a13 --- /dev/null +++ b/easy_ViTPose/configs/ViTPose_wholebody.py @@ -0,0 +1,20 @@ +from .ViTPose_common import * + +# Channel configuration +channel_cfg = dict( + num_output_channels=133, + dataset_joints=133, + dataset_channel=[ + list(range(133)), + ], + inference_channel=list(range(133))) + +# Set models channels +data_cfg['num_output_channels'] = channel_cfg['num_output_channels'] +data_cfg['num_joints']= channel_cfg['dataset_joints'] +data_cfg['dataset_channel']= channel_cfg['dataset_channel'] +data_cfg['inference_channel']= channel_cfg['inference_channel'] + +names = ['small', 'base', 'large', 'huge'] +for name in names: + globals()[f'model_{name}']['keypoint_head']['out_channels'] = channel_cfg['num_output_channels'] diff --git a/easy_ViTPose/configs/__init__.py b/easy_ViTPose/configs/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/easy_ViTPose/datasets/COCO.py b/easy_ViTPose/datasets/COCO.py new file mode 100644 index 0000000000000000000000000000000000000000..3c3d850312f0e1ac04b39ef6e470fade8067d90d --- /dev/null +++ b/easy_ViTPose/datasets/COCO.py @@ -0,0 +1,556 @@ +# Part of this code is derived/taken from https://github.com/leoxiaobin/deep-high-resolution-net.pytorch +import os +import sys +import pickle +import random + +import cv2 +import json_tricks as json +import numpy as np +from pycocotools.coco import COCO +from torchvision import transforms +import torchvision.transforms.functional as F +from tqdm import tqdm +from PIL import Image + +from .HumanPoseEstimation import HumanPoseEstimationDataset as Dataset + +sys.path.append(os.path.dirname(os.path.dirname(__file__))) +from vit_utils.transform import fliplr_joints, affine_transform, get_affine_transform + +import numpy as np + + +class COCODataset(Dataset): + """ + COCODataset class. + """ + + def __init__(self, root_path="./datasets/COCO", data_version="train2017", + is_train=True, use_gt_bboxes=True, bbox_path="", + image_width=288, image_height=384, + scale=True, scale_factor=0.35, flip_prob=0.5, rotate_prob=0.5, rotation_factor=45., half_body_prob=0.3, + use_different_joints_weight=False, heatmap_sigma=3, soft_nms=False): + """ + Initializes a new COCODataset object. + + Image and annotation indexes are loaded and stored in memory. + Annotations are preprocessed to have a simple list of annotations to iterate over. + + Bounding boxes can be loaded from the ground truth or from a pickle file (in this case, no annotations are + provided). + + Args: + root_path (str): dataset root path. + Default: "./datasets/COCO" + data_version (str): desired version/folder of COCO. Possible options are "train2017", "val2017". + Default: "train2017" + is_train (bool): train or eval mode. If true, train mode is used. + Default: True + use_gt_bboxes (bool): use ground truth bounding boxes. If False, bbox_path is required. + Default: True + bbox_path (str): bounding boxes pickle file path. + Default: "" + image_width (int): image width. + Default: 288 + image_height (int): image height. + Default: ``384`` + color_rgb (bool): rgb or bgr color mode. If True, rgb color mode is used. + Default: True + scale (bool): scale mode. + Default: True + scale_factor (float): scale factor. + Default: 0.35 + flip_prob (float): flip probability. + Default: 0.5 + rotate_prob (float): rotate probability. + Default: 0.5 + rotation_factor (float): rotation factor. + Default: 45. + half_body_prob (float): half body probability. + Default: 0.3 + use_different_joints_weight (bool): use different joints weights. + If true, the following joints weights will be used: + [1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5, 1.5] + Default: False + heatmap_sigma (float): sigma of the gaussian used to create the heatmap. + Default: 3 + soft_nms (bool): enable soft non-maximum suppression. + Default: False + """ + super(COCODataset, self).__init__() + + self.root_path = root_path + self.data_version = data_version + self.is_train = is_train + self.use_gt_bboxes = use_gt_bboxes + self.bbox_path = bbox_path + self.scale = scale # ToDo Check + self.scale_factor = scale_factor + self.flip_prob = flip_prob + self.rotate_prob = rotate_prob + self.rotation_factor = rotation_factor + self.half_body_prob = half_body_prob + self.use_different_joints_weight = use_different_joints_weight # ToDo Check + self.heatmap_sigma = heatmap_sigma + self.soft_nms = soft_nms + + # Image & annotation path + self.data_path = f"{root_path}/{data_version}" + self.annotation_path = f"{root_path}/annotations/person_keypoints_{data_version}.json" + + self.image_size = (image_width, image_height) + self.aspect_ratio = image_width * 1.0 / image_height + + self.heatmap_size = (int(image_width / 4), int(image_height / 4)) + self.heatmap_type = 'gaussian' + self.pixel_std = 200 # I don't understand the meaning of pixel_std (=200) in the original implementation + + self.num_joints = 25 + self.num_joints_half_body = 15 + + # eye, ear, shoulder, elbow, wrist, hip, knee, ankle + self.flip_pairs = [[1, 2], [3, 4], [6, 7], [8, 9], [10, 11], [12, 13], + [15, 16], [17, 18], [19, 22], [20, 23], [21, 24]] + self.upper_body_ids = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] + self.lower_body_ids = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22] + self.joints_weight = np.array([1., 1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, + 1.5, 1.5, 1., 1., 1., 1.2, 1.2, 1.5, 1.5, + 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5]).reshape((self.num_joints, 1)) + + self.transform = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ]) + + # Load COCO dataset - Create COCO object then load images and annotations + self.coco = COCO(self.annotation_path) + + # Create a list of annotations and the corresponding image (each image can contain more than one detection) + + """ Load bboxes and joints + - if self.use_gt_bboxes -> Load GT bboxes and joints + - else -> Load pre-predicted bboxes by a detector (as YOLOv3) and null joints + """ + + if not self.use_gt_bboxes: + """ + bboxes must be saved as the original COCO annotations + i.e. the format must be: + bboxes = { + '': [ + { + 'id': , # progressive id for debugging + 'clean_bbox': np.array([, , , ])} + }, + ... + ], + ... + } + """ + with open(self.bbox_path, 'rb') as fd: + bboxes = pickle.load(fd) + + self.data = [] + # load annotations for each image of COCO + for imgId in tqdm(self.coco.getImgIds(), desc="Prepare images, annotations ... "): + ann_ids = self.coco.getAnnIds(imgIds=imgId, iscrowd=False) # annotation ids + img = self.coco.loadImgs(imgId)[0] # load img + + if self.use_gt_bboxes: + objs = self.coco.loadAnns(ann_ids) + + # sanitize bboxes + valid_objs = [] + for obj in objs: + # Skip non-person objects (it should never happen) + if obj['category_id'] != 1: + continue + + # ignore objs without keypoints annotation + if max(obj['keypoints']) == 0 and max(obj['foot_kpts']) == 0: + continue + + x, y, w, h = obj['bbox'] + x1 = np.max((0, x)) + y1 = np.max((0, y)) + x2 = np.min((img['width'] - 1, x1 + np.max((0, w - 1)))) + y2 = np.min((img['height'] - 1, y1 + np.max((0, h - 1)))) + + # Use only valid bounding boxes + if obj['area'] > 0 and x2 >= x1 and y2 >= y1: + obj['clean_bbox'] = [x1, y1, x2 - x1, y2 - y1] + valid_objs.append(obj) + + objs = valid_objs + + else: + objs = bboxes[imgId] + + # for each annotation of this image, add the formatted annotation to self.data + for obj in objs: + joints = np.zeros((self.num_joints, 2), dtype=np.float) + joints_visibility = np.ones((self.num_joints, 2), dtype=np.float) + + # Add foot data to keypoints + obj['keypoints'].extend(obj['foot_kpts']) + + if self.use_gt_bboxes: + """ COCO pre-processing + + - Moved above + - Skip non-person objects (it should never happen) + if obj['category_id'] != 1: + continue + + # ignore objs without keypoints annotation + if max(obj['keypoints']) == 0: + continue + """ + + # Not all joints are already present, skip them + vjoints = list(range(self.num_joints)) + vjoints.remove(5) + vjoints.remove(14) + + for idx, pt in enumerate(vjoints): + if pt == 5 or pt == 14: + continue # Neck and hip are manually filled + joints[pt, 0] = obj['keypoints'][idx * 3 + 0] + joints[pt, 1] = obj['keypoints'][idx * 3 + 1] + t_vis = int(np.clip(obj['keypoints'][idx * 3 + 2], 0, 1)) + """ + - COCO: + if visibility == 0 -> keypoint is not in the image. + if visibility == 1 -> keypoint is in the image BUT not visible + (e.g. behind an object). + if visibility == 2 -> keypoint looks clearly + (i.e. it is not hidden). + """ + joints_visibility[pt, 0] = t_vis + joints_visibility[pt, 1] = t_vis + + center, scale = self._box2cs(obj['clean_bbox'][:4]) + + # Add neck and c-hip (check utils/visualization.py for keypoints) + joints[5, 0] = (joints[6, 0] + joints[7, 0]) / 2 + joints[5, 1] = (joints[6, 1] + joints[7, 1]) / 2 + joints_visibility[5, :] = min(joints_visibility[6, 0], + joints_visibility[7, 0]) + joints[14, 0] = (joints[12, 0] + joints[13, 0]) / 2 + joints[14, 1] = (joints[12, 1] + joints[13, 1]) / 2 + joints_visibility[14, :] = min(joints_visibility[12, 0], + joints_visibility[13, 0]) + + self.data.append({ + 'imgId': imgId, + 'annId': obj['id'], + 'imgPath': f"{self.root_path}/{self.data_version}/{imgId:012d}.jpg", + 'center': center, + 'scale': scale, + 'joints': joints, + 'joints_visibility': joints_visibility, + }) + + # Done check if we need prepare_data -> We should not + print('\nCOCO dataset loaded!') + + # Default values + self.bbox_thre = 1.0 + self.image_thre = 0.0 + self.in_vis_thre = 0.2 + self.nms_thre = 1.0 + self.oks_thre = 0.9 + + def __len__(self): + return len(self.data) + + def __getitem__(self, index): + # index = 0 + joints_data = self.data[index].copy() + + # Load image + try: + image = np.array(Image.open(joints_data['imgPath'])) + if image.ndim == 2: + # Some images are grayscale and will fail the trasform, convert to RGB + image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) + except: + raise ValueError(f"Fail to read {joints_data['imgPath']}") + + joints = joints_data['joints'] + joints_vis = joints_data['joints_visibility'] + + c = joints_data['center'] + s = joints_data['scale'] + score = joints_data['score'] if 'score' in joints_data else 1 + r = 0 + + # Apply data augmentation + if self.is_train: + if (self.half_body_prob and random.random() < self.half_body_prob and + np.sum(joints_vis[:, 0]) > self.num_joints_half_body): + c_half_body, s_half_body = self._half_body_transform(joints, joints_vis) + + if c_half_body is not None and s_half_body is not None: + c, s = c_half_body, s_half_body + + sf = self.scale_factor + rf = self.rotation_factor + + if self.scale: + # A random scale factor in [1 - sf, 1 + sf] + s = s * np.clip(random.random() * sf + 1, 1 - sf, 1 + sf) + + if self.rotate_prob and random.random() < self.rotate_prob: + # A random rotation factor in [-2 * rf, 2 * rf] + r = np.clip(random.random() * rf, -rf * 2, rf * 2) + else: + r = 0 + + if self.flip_prob and random.random() < self.flip_prob: + image = image[:, ::-1, :] + joints, joints_vis = fliplr_joints(joints, joints_vis, + image.shape[1], + self.flip_pairs) + c[0] = image.shape[1] - c[0] - 1 + + # Apply affine transform on joints and image + trans = get_affine_transform(c, s, self.pixel_std, r, self.image_size) + image = cv2.warpAffine( + image, + trans, + (int(self.image_size[0]), int(self.image_size[1])), + flags=cv2.INTER_LINEAR + ) + + for i in range(self.num_joints): + if joints_vis[i, 0] > 0.: + joints[i, 0:2] = affine_transform(joints[i, 0:2], trans) + + # Convert image to tensor and normalize + if self.transform is not None: # I could remove this check + image = self.transform(image) + + target, target_weight = self._generate_target(joints, joints_vis) + + # Update metadata + joints_data['joints'] = joints + joints_data['joints_visibility'] = joints_vis + joints_data['center'] = c + joints_data['scale'] = s + joints_data['rotation'] = r + joints_data['score'] = score + + # from utils.visualization import draw_points_and_skeleton, joints_dict + # image = np.rollaxis(image.detach().cpu().numpy(), 0, 3) + # joints = np.hstack((joints[:, ::-1], joints_vis[:, 0][..., None])) + # image = draw_points_and_skeleton(image.copy(), joints, + # joints_dict()['coco']['skeleton'], + # person_index=0, + # points_color_palette='gist_rainbow', + # skeleton_color_palette='jet', + # points_palette_samples=10, + # confidence_threshold=0.4) + # cv2.imshow('', image) + # cv2.waitKey(0) + + return image, target.astype(np.float32), target_weight.astype(np.float32), joints_data + + + # Private methods + def _box2cs(self, box): + x, y, w, h = box[:4] + return self._xywh2cs(x, y, w, h) + + def _xywh2cs(self, x, y, w, h): + center = np.zeros((2,), dtype=np.float32) + center[0] = x + w * 0.5 + center[1] = y + h * 0.5 + + if w > self.aspect_ratio * h: + h = w * 1.0 / self.aspect_ratio + elif w < self.aspect_ratio * h: + w = h * self.aspect_ratio + scale = np.array( + [w * 1.0 / self.pixel_std, h * 1.0 / self.pixel_std], + dtype=np.float32) + if center[0] != -1: + scale = scale * 1.25 + + return center, scale + + def _half_body_transform(self, joints, joints_vis): + upper_joints = [] + lower_joints = [] + for joint_id in range(self.num_joints): + if joints_vis[joint_id][0] > 0: + if joint_id in self.upper_body_ids: + upper_joints.append(joints[joint_id]) + else: + lower_joints.append(joints[joint_id]) + + if random.random() < 0.5 and len(upper_joints) > 2: + selected_joints = upper_joints + else: + selected_joints = lower_joints \ + if len(lower_joints) > 2 else upper_joints + + if len(selected_joints) < 2: + return None, None + + selected_joints = np.array(selected_joints, dtype=np.float32) + center = selected_joints.mean(axis=0)[:2] + + left_top = np.amin(selected_joints, axis=0) + right_bottom = np.amax(selected_joints, axis=0) + + w = right_bottom[0] - left_top[0] + h = right_bottom[1] - left_top[1] + + if w > self.aspect_ratio * h: + h = w * 1.0 / self.aspect_ratio + elif w < self.aspect_ratio * h: + w = h * self.aspect_ratio + + scale = np.array( + [ + w * 1.0 / self.pixel_std, + h * 1.0 / self.pixel_std + ], + dtype=np.float32 + ) + + scale = scale * 1.5 + + return center, scale + + def _generate_target(self, joints, joints_vis): + """ + :param joints: [num_joints, 2] + :param joints_vis: [num_joints, 2] + :return: target, target_weight(1: visible, 0: invisible) + """ + target_weight = np.ones((self.num_joints, 1), dtype=np.float32) + target_weight[:, 0] = joints_vis[:, 0] + + if self.heatmap_type == 'gaussian': + target = np.zeros((self.num_joints, + self.heatmap_size[1], + self.heatmap_size[0]), + dtype=np.float32) + + tmp_size = self.heatmap_sigma * 3 + + for joint_id in range(self.num_joints): + feat_stride = np.asarray(self.image_size) / np.asarray(self.heatmap_size) + mu_x = int(joints[joint_id][0] / feat_stride[0] + 0.5) + mu_y = int(joints[joint_id][1] / feat_stride[1] + 0.5) + # Check that any part of the gaussian is in-bounds + ul = [int(mu_x - tmp_size), int(mu_y - tmp_size)] + br = [int(mu_x + tmp_size + 1), int(mu_y + tmp_size + 1)] + if ul[0] >= self.heatmap_size[0] or ul[1] >= self.heatmap_size[1] \ + or br[0] < 0 or br[1] < 0: + # If not, just return the image as is + target_weight[joint_id] = 0 + continue + + # # Generate gaussian + size = 2 * tmp_size + 1 + x = np.arange(0, size, 1, np.float32) + y = x[:, np.newaxis] + x0 = y0 = size // 2 + # The gaussian is not normalized, we want the center value to equal 1 + g = np.exp(- ((x - x0) ** 2 + (y - y0) ** 2) / (2 * self.heatmap_sigma ** 2)) + + # Usable gaussian range + g_x = max(0, -ul[0]), min(br[0], self.heatmap_size[0]) - ul[0] + g_y = max(0, -ul[1]), min(br[1], self.heatmap_size[1]) - ul[1] + # Image range + img_x = max(0, ul[0]), min(br[0], self.heatmap_size[0]) + img_y = max(0, ul[1]), min(br[1], self.heatmap_size[1]) + + v = target_weight[joint_id] + if v > 0.5: + target[joint_id][img_y[0]:img_y[1], img_x[0]:img_x[1]] = \ + g[g_y[0]:g_y[1], g_x[0]:g_x[1]] + else: + raise NotImplementedError + + if self.use_different_joints_weight: + target_weight = np.multiply(target_weight, self.joints_weight) + + return target, target_weight + + def _write_coco_keypoint_results(self, keypoints, res_file): + data_pack = [ + { + 'cat_id': 1, # 1 == 'person' + 'cls': 'person', + 'ann_type': 'keypoints', + 'keypoints': keypoints + } + ] + + results = self._coco_keypoint_results_one_category_kernel(data_pack[0]) + with open(res_file, 'w') as f: + json.dump(results, f, sort_keys=True, indent=4) + try: + json.load(open(res_file)) + except Exception: + content = [] + with open(res_file, 'r') as f: + for line in f: + content.append(line) + content[-1] = ']' + with open(res_file, 'w') as f: + for c in content: + f.write(c) + + def _coco_keypoint_results_one_category_kernel(self, data_pack): + cat_id = data_pack['cat_id'] + keypoints = data_pack['keypoints'] + cat_results = [] + + for img_kpts in keypoints: + if len(img_kpts) == 0: + continue + + _key_points = np.array([img_kpts[k]['keypoints'] for k in range(len(img_kpts))], dtype=np.float32) + key_points = np.zeros((_key_points.shape[0], self.num_joints * 3), dtype=np.float32) + + for ipt in range(self.num_joints): + key_points[:, ipt * 3 + 0] = _key_points[:, ipt, 0] + key_points[:, ipt * 3 + 1] = _key_points[:, ipt, 1] + key_points[:, ipt * 3 + 2] = _key_points[:, ipt, 2] # keypoints score. + + result = [ + { + 'image_id': img_kpts[k]['image'], + 'category_id': cat_id, + 'keypoints': list(key_points[k]), + 'score': img_kpts[k]['score'].astype(np.float32), + 'center': list(img_kpts[k]['center']), + 'scale': list(img_kpts[k]['scale']) + } + for k in range(len(img_kpts)) + ] + cat_results.extend(result) + + return cat_results + + +if __name__ == '__main__': + # from skimage import io + coco = COCODataset(root_path=f"{os.path.dirname(__file__)}/COCO", data_version="traincoex", rotate_prob=0., half_body_prob=0.) + item = coco[1] + # io.imsave("tmp.jpg", item[0].permute(1,2,0).numpy()) + print() + print(item[1].shape) + print('ok!!') + # img = np.clip(np.transpose(item[0].numpy(), (1, 2, 0))[:, :, ::-1] * np.asarray([0.229, 0.224, 0.225]) + + # np.asarray([0.485, 0.456, 0.406]), 0, 1) * 255 + # cv2.imwrite('./tmp.png', img.astype(np.uint8)) + # print(item[-1]) + pass diff --git a/easy_ViTPose/datasets/HumanPoseEstimation.py b/easy_ViTPose/datasets/HumanPoseEstimation.py new file mode 100644 index 0000000000000000000000000000000000000000..1a20727565386e2e5022e12e1f8e6bc5c2c97441 --- /dev/null +++ b/easy_ViTPose/datasets/HumanPoseEstimation.py @@ -0,0 +1,17 @@ +from torch.utils.data import Dataset + + +class HumanPoseEstimationDataset(Dataset): + """ + HumanPoseEstimationDataset class. + + Generic class for HPE datasets. + """ + def __init__(self): + pass + + def __len__(self): + pass + + def __getitem__(self, item): + pass \ No newline at end of file diff --git a/easy_ViTPose/datasets/__init__.py b/easy_ViTPose/datasets/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/easy_ViTPose/easy_ViTPose.egg-info/PKG-INFO b/easy_ViTPose/easy_ViTPose.egg-info/PKG-INFO new file mode 100644 index 0000000000000000000000000000000000000000..ffffcae0e804ef5280eabaf6fd9b58f2a726fd23 --- /dev/null +++ b/easy_ViTPose/easy_ViTPose.egg-info/PKG-INFO @@ -0,0 +1,4 @@ +Metadata-Version: 2.1 +Name: easy-ViTPose +Version: 0.1 +License-File: LICENSE diff --git a/easy_ViTPose/easy_ViTPose.egg-info/SOURCES.txt b/easy_ViTPose/easy_ViTPose.egg-info/SOURCES.txt new file mode 100644 index 0000000000000000000000000000000000000000..c21ace0d265ba58ae5f43d116731d76998826549 --- /dev/null +++ b/easy_ViTPose/easy_ViTPose.egg-info/SOURCES.txt @@ -0,0 +1,35 @@ +LICENSE +README.md +setup.py +src/easy_ViTPose.egg-info/PKG-INFO +src/easy_ViTPose.egg-info/SOURCES.txt +src/easy_ViTPose.egg-info/dependency_links.txt +src/easy_ViTPose.egg-info/top_level.txt +src/vit_models/__init__.py +src/vit_models/model.py +src/vit_models/optimizer.py +src/vit_models/losses/__init__.py +src/vit_models/losses/classfication_loss.py +src/vit_models/losses/heatmap_loss.py +src/vit_models/losses/mesh_loss.py +src/vit_models/losses/mse_loss.py +src/vit_models/losses/multi_loss_factory.py +src/vit_models/losses/regression_loss.py +src/vit_utils/__init__.py +src/vit_utils/dist_util.py +src/vit_utils/inference.py +src/vit_utils/logging.py +src/vit_utils/top_down_eval.py +src/vit_utils/train_valid_fn.py +src/vit_utils/transform.py +src/vit_utils/util.py +src/vit_utils/visualization.py +src/vit_utils/nms/__init__.py +src/vit_utils/nms/nms.py +src/vit_utils/nms/nms_ori.py +src/vit_utils/nms/setup_linux.py +src/vit_utils/post_processing/__init__.py +src/vit_utils/post_processing/group.py +src/vit_utils/post_processing/nms.py +src/vit_utils/post_processing/one_euro_filter.py +src/vit_utils/post_processing/post_transforms.py \ No newline at end of file diff --git a/easy_ViTPose/easy_ViTPose.egg-info/dependency_links.txt b/easy_ViTPose/easy_ViTPose.egg-info/dependency_links.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/easy_ViTPose/easy_ViTPose.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/easy_ViTPose/easy_ViTPose.egg-info/top_level.txt b/easy_ViTPose/easy_ViTPose.egg-info/top_level.txt new file mode 100644 index 0000000000000000000000000000000000000000..6834310e840f5badb7d936ffe33fd04c3ebfbd55 --- /dev/null +++ b/easy_ViTPose/easy_ViTPose.egg-info/top_level.txt @@ -0,0 +1,2 @@ +vit_models +vit_utils diff --git a/easy_ViTPose/inference.py b/easy_ViTPose/inference.py new file mode 100644 index 0000000000000000000000000000000000000000..abba30d0254352143c5cc394affc7515f9a31e4b --- /dev/null +++ b/easy_ViTPose/inference.py @@ -0,0 +1,334 @@ +import abc +import os +from typing import Optional +import typing + +import cv2 +import numpy as np +import torch + +from ultralytics import YOLO + +from .configs.ViTPose_common import data_cfg +from .sort import Sort +from .vit_models.model import ViTPose +from .vit_utils.inference import draw_bboxes, pad_image +from .vit_utils.top_down_eval import keypoints_from_heatmaps +from .vit_utils.util import dyn_model_import, infer_dataset_by_path +from .vit_utils.visualization import draw_points_and_skeleton, joints_dict + +try: + import torch_tensorrt +except ModuleNotFoundError: + pass + +try: + import onnxruntime +except ModuleNotFoundError: + pass + +__all__ = ['VitInference'] +np.bool = np.bool_ +MEAN = [0.485, 0.456, 0.406] +STD = [0.229, 0.224, 0.225] + + +DETC_TO_YOLO_YOLOC = { + 'human': [0], + 'cat': [15], + 'dog': [16], + 'horse': [17], + 'sheep': [18], + 'cow': [19], + 'elephant': [20], + 'bear': [21], + 'zebra': [22], + 'giraffe': [23], + 'animals': [15, 16, 17, 18, 19, 20, 21, 22, 23] +} + + +class VitInference: + """ + Class for performing inference using ViTPose models with YOLOv8 human detection and SORT tracking. + + Args: + model (str): Path to the ViT model file (.pth, .onnx, .engine). + yolo (str): Path of the YOLOv8 model to load. + model_name (str, optional): Name of the ViT model architecture to use. + Valid values are 's', 'b', 'l', 'h'. + Defaults to None, is necessary when using .pth checkpoints. + det_class (str, optional): the detection class. if None it is inferred by the dataset. + valid values are 'human', 'cat', 'dog', 'horse', 'sheep', + 'cow', 'elephant', 'bear', 'zebra', 'giraffe', + 'animals' (which is all previous but human) + dataset (str, optional): Name of the dataset. If None it's extracted from the file name. + Valid values are 'coco', 'coco_25', 'wholebody', 'mpii', + 'ap10k', 'apt36k', 'aic' + yolo_size (int, optional): Size of the input image for YOLOv8 model. Defaults to 320. + device (str, optional): Device to use for inference. Defaults to 'cuda' if available, else 'cpu'. + is_video (bool, optional): Flag indicating if the input is video. Defaults to False. + single_pose (bool, optional): Flag indicating if the video (on images this flag has no effect) + will contain a single pose. + In this case the SORT tracker is not used (increasing performance) + but people id tracking + won't be consistent among frames. + yolo_step (int, optional): The tracker can be used to predict the bboxes instead of yolo for performance, + this flag specifies how often yolo is applied (e.g. 1 applies yolo every frame). + This does not have any effect when is_video is False. + """ + + def __init__(self, model: str, + yolo: str, + model_name: Optional[str] = None, + det_class: Optional[str] = None, + dataset: Optional[str] = None, + yolo_size: Optional[int] = 320, + device: Optional[str] = None, + is_video: Optional[bool] = False, + single_pose: Optional[bool] = False, + yolo_step: Optional[int] = 1): + assert os.path.isfile(model), f'The model file {model} does not exist' + assert os.path.isfile(yolo), f'The YOLOv8 model {yolo} does not exist' + + # Device priority is cuda / mps / cpu + if device is None: + if torch.cuda.is_available(): + device = 'cuda' + elif hasattr(torch.backends, 'mps') and torch.backends.mps.is_available(): + device = 'mps' + else: + device = 'cpu' + + self.device = device + self.yolo = YOLO(yolo, task='detect') + self.yolo_size = yolo_size + self.yolo_step = yolo_step + self.is_video = is_video + self.single_pose = single_pose + self.reset() + + # State saving during inference + self.save_state = True # Can be disabled manually + self._img = None + self._yolo_res = None + self._tracker_res = None + self._keypoints = None + + # Use extension to decide which kind of model has been loaded + use_onnx = model.endswith('.onnx') + use_trt = model.endswith('.engine') + + + # Extract dataset name + if dataset is None: + dataset = infer_dataset_by_path(model) + + assert dataset in ['mpii', 'coco', 'coco_25', 'wholebody', 'aic', 'ap10k', 'apt36k'], \ + 'The specified dataset is not valid' + + # Dataset can now be set for visualization + self.dataset = dataset + + # if we picked the dataset switch to correct yolo classes if not set + if det_class is None: + det_class = 'animals' if dataset in ['ap10k', 'apt36k'] else 'human' + self.yolo_classes = DETC_TO_YOLO_YOLOC[det_class] + + assert model_name in [None, 's', 'b', 'l', 'h'], \ + f'The model name {model_name} is not valid' + + # onnx / trt models do not require model_cfg specification + if model_name is None: + assert use_onnx or use_trt, \ + 'Specify the model_name if not using onnx / trt' + else: + # Dynamically import the model class + model_cfg = dyn_model_import(self.dataset, model_name) + + self.target_size = data_cfg['image_size'] + if use_onnx: + self._ort_session = onnxruntime.InferenceSession(model, + providers=['CUDAExecutionProvider', + 'CPUExecutionProvider']) + inf_fn = self._inference_onnx + else: + self._vit_pose = ViTPose(model_cfg) + self._vit_pose.eval() + + if use_trt: + self._vit_pose = torch.jit.load(model) + else: + ckpt = torch.load(model, map_location='cpu') + if 'state_dict' in ckpt: + self._vit_pose.load_state_dict(ckpt['state_dict']) + else: + self._vit_pose.load_state_dict(ckpt) + self._vit_pose.to(torch.device(device)) + + inf_fn = self._inference_torch + + # Override _inference abstract with selected engine + self._inference = inf_fn # type: ignore + + def reset(self): + """ + Reset the inference class to be ready for a new video. + This will reset the internal counter of frames, on videos + this is necessary to reset the tracker. + """ + min_hits = 3 if self.yolo_step == 1 else 1 + use_tracker = self.is_video and not self.single_pose + self.tracker = Sort(max_age=self.yolo_step, + min_hits=min_hits, + iou_threshold=0.3) if use_tracker else None # TODO: Params + self.frame_counter = 0 + + @classmethod + def postprocess(cls, heatmaps, org_w, org_h): + """ + Postprocess the heatmaps to obtain keypoints and their probabilities. + + Args: + heatmaps (ndarray): Heatmap predictions from the model. + org_w (int): Original width of the image. + org_h (int): Original height of the image. + + Returns: + ndarray: Processed keypoints with probabilities. + """ + points, prob = keypoints_from_heatmaps(heatmaps=heatmaps, + center=np.array([[org_w // 2, + org_h // 2]]), + scale=np.array([[org_w, org_h]]), + unbiased=True, use_udp=True) + return np.concatenate([points[:, :, ::-1], prob], axis=2) + + @abc.abstractmethod + def _inference(self, img: np.ndarray) -> np.ndarray: + """ + Abstract method for performing inference on an image. + It is overloaded by each inference engine. + + Args: + img (ndarray): Input image for inference. + + Returns: + ndarray: Inference results. + """ + raise NotImplementedError + + def inference(self, img: np.ndarray) -> dict[typing.Any, typing.Any]: + """ + Perform inference on the input image. + + Args: + img (ndarray): Input image for inference in RGB format. + + Returns: + dict[typing.Any, typing.Any]: Inference results. + """ + + # First use YOLOv8 for detection + res_pd = np.empty((0, 5)) + results = None + if (self.tracker is None or + (self.frame_counter % self.yolo_step == 0 or self.frame_counter < 3)): + results = self.yolo(img, verbose=False, imgsz=self.yolo_size, + device=self.device if self.device != 'cuda' else 0, + classes=self.yolo_classes)[0] + res_pd = np.array([r[:5].tolist() for r in # TODO: Confidence threshold + results.boxes.data.cpu().numpy() if r[4] > 0.35]).reshape((-1, 5)) + self.frame_counter += 1 + + frame_keypoints = {} + ids = None + if self.tracker is not None: + res_pd = self.tracker.update(res_pd) + ids = res_pd[:, 5].astype(int).tolist() + + # Prepare boxes for inference + bboxes = res_pd[:, :4].round().astype(int) + scores = res_pd[:, 4].tolist() + pad_bbox = 10 + + if ids is None: + ids = range(len(bboxes)) + + for bbox, id in zip(bboxes, ids): + # TODO: Slightly bigger bbox + bbox[[0, 2]] = np.clip(bbox[[0, 2]] + [-pad_bbox, pad_bbox], 0, img.shape[1]) + bbox[[1, 3]] = np.clip(bbox[[1, 3]] + [-pad_bbox, pad_bbox], 0, img.shape[0]) + + # Crop image and pad to 3/4 aspect ratio + img_inf = img[bbox[1]:bbox[3], bbox[0]:bbox[2]] + img_inf, (left_pad, top_pad) = pad_image(img_inf, 3 / 4) + + keypoints = self._inference(img_inf)[0] + # Transform keypoints to original image + keypoints[:, :2] += bbox[:2][::-1] - [top_pad, left_pad] + frame_keypoints[id] = keypoints + + if self.save_state: + self._img = img + self._yolo_res = results + self._tracker_res = (bboxes, ids, scores) + self._keypoints = frame_keypoints + + return frame_keypoints + + def draw(self, show_yolo=True, show_raw_yolo=False, confidence_threshold=0.5): + """ + Draw keypoints and bounding boxes on the image. + + Args: + show_yolo (bool, optional): Whether to show YOLOv8 bounding boxes. Default is True. + show_raw_yolo (bool, optional): Whether to show raw YOLOv8 bounding boxes. Default is False. + + Returns: + ndarray: Image with keypoints and bounding boxes drawn. + """ + img = self._img.copy() + bboxes, ids, scores = self._tracker_res + + if self._yolo_res is not None and (show_raw_yolo or (self.tracker is None and show_yolo)): + img = np.array(self._yolo_res.plot()) + + if show_yolo and self.tracker is not None: + img = draw_bboxes(img, bboxes, ids, scores) + + img = np.array(img)[..., ::-1] # RGB to BGR for cv2 modules + for idx, k in self._keypoints.items(): + img = draw_points_and_skeleton(img.copy(), k, + joints_dict()[self.dataset]['skeleton'], + person_index=idx, + points_color_palette='gist_rainbow', + skeleton_color_palette='jet', + points_palette_samples=10, + confidence_threshold=confidence_threshold) + return img[..., ::-1] # Return RGB as original + + def pre_img(self, img): + org_h, org_w = img.shape[:2] + img_input = cv2.resize(img, self.target_size, interpolation=cv2.INTER_LINEAR) / 255 + img_input = ((img_input - MEAN) / STD).transpose(2, 0, 1)[None].astype(np.float32) + return img_input, org_h, org_w + + @torch.no_grad() + def _inference_torch(self, img: np.ndarray) -> np.ndarray: + # Prepare input data + img_input, org_h, org_w = self.pre_img(img) + img_input = torch.from_numpy(img_input).to(torch.device(self.device)) + + # Feed to model + heatmaps = self._vit_pose(img_input).detach().cpu().numpy() + return self.postprocess(heatmaps, org_w, org_h) + + def _inference_onnx(self, img: np.ndarray) -> np.ndarray: + # Prepare input data + img_input, org_h, org_w = self.pre_img(img) + + # Feed to model + ort_inputs = {self._ort_session.get_inputs()[0].name: img_input} + heatmaps = self._ort_session.run(None, ort_inputs)[0] + return self.postprocess(heatmaps, org_w, org_h) \ No newline at end of file diff --git a/easy_ViTPose/sort.py b/easy_ViTPose/sort.py new file mode 100644 index 0000000000000000000000000000000000000000..daf2fd34cca5de7cbf5dbd7940a7e24dad176b1e --- /dev/null +++ b/easy_ViTPose/sort.py @@ -0,0 +1,266 @@ +""" + SORT: A Simple, Online and Realtime Tracker + Copyright (C) 2016-2020 Alex Bewley alex@bewley.ai + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +""" +from __future__ import print_function + +import os +import numpy as np +import matplotlib + +import matplotlib.pyplot as plt +import matplotlib.patches as patches +from skimage import io + +import glob +import time +import argparse +from filterpy.kalman import KalmanFilter + +np.random.seed(0) + + +def linear_assignment(cost_matrix): + try: + import lap + _, x, y = lap.lapjv(cost_matrix, extend_cost=True) + return np.array([[y[i], i] for i in x if i >= 0]) + except ImportError: + from scipy.optimize import linear_sum_assignment + x, y = linear_sum_assignment(cost_matrix) + return np.array(list(zip(x, y))) + + +def iou_batch(bb_test, bb_gt): + """ + From SORT: Computes IOU between two bboxes in the form [x1,y1,x2,y2] + """ + bb_gt = np.expand_dims(bb_gt, 0) + bb_test = np.expand_dims(bb_test, 1) + + xx1 = np.maximum(bb_test[..., 0], bb_gt[..., 0]) + yy1 = np.maximum(bb_test[..., 1], bb_gt[..., 1]) + xx2 = np.minimum(bb_test[..., 2], bb_gt[..., 2]) + yy2 = np.minimum(bb_test[..., 3], bb_gt[..., 3]) + w = np.maximum(0., xx2 - xx1) + h = np.maximum(0., yy2 - yy1) + wh = w * h + o = wh / ((bb_test[..., 2] - bb_test[..., 0]) * (bb_test[..., 3] - bb_test[..., 1]) + + (bb_gt[..., 2] - bb_gt[..., 0]) * (bb_gt[..., 3] - bb_gt[..., 1]) - wh) + return(o) + + +def convert_bbox_to_z(bbox): + """ + Takes a bounding box in the form [x1,y1,x2,y2] and returns z in the form + [x,y,s,r] where x,y is the centre of the box and s is the scale/area and r is + the aspect ratio + """ + w = bbox[2] - bbox[0] + h = bbox[3] - bbox[1] + x = bbox[0] + w/2. + y = bbox[1] + h/2. + s = w * h # scale is just area + r = w / float(h) + return np.array([x, y, s, r]).reshape((4, 1)) + + +def convert_x_to_bbox(x, score=None): + """ + Takes a bounding box in the centre form [x,y,s,r] and returns it in the form + [x1,y1,x2,y2] where x1,y1 is the top left and x2,y2 is the bottom right + """ + w = np.sqrt(x[2] * x[3]) + h = x[2] / w + if(score == None): + return np.array([x[0]-w/2., x[1]-h/2., x[0]+w/2., x[1]+h/2.]).reshape((1, 4)) + else: + return np.array([x[0]-w/2., x[1]-h/2., x[0]+w/2., x[1]+h/2., score]).reshape((1, 5)) + + +class KalmanBoxTracker(object): + """ + This class represents the internal state of individual tracked objects observed as bbox. + """ + count = 0 + + def __init__(self, bbox, score): + """ + Initialises a tracker using initial bounding box. + """ + # define constant velocity model + self.kf = KalmanFilter(dim_x=7, dim_z=4) + self.kf.F = np.array([[1, 0, 0, 0, 1, 0, 0], [0, 1, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 1], [ + 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]]) + self.kf.H = np.array([[1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0]]) + + self.kf.R[2:, 2:] *= 10. + self.kf.P[4:, 4:] *= 1000. # give high uncertainty to the unobservable initial velocities + self.kf.P *= 10. + self.kf.Q[-1, -1] *= 0.01 + self.kf.Q[4:, 4:] *= 0.01 + + self.kf.x[:4] = convert_bbox_to_z(bbox) + self.time_since_update = 0 + self.id = KalmanBoxTracker.count + KalmanBoxTracker.count += 1 + self.history = [] + self.hits = 0 + self.hit_streak = 0 + self.age = 0 + self.score = score + + def update(self, bbox, score): + """ + Updates the state vector with observed bbox. + """ + self.time_since_update = 0 + self.history = [] + self.hits += 1 + self.hit_streak += 1 + self.kf.update(convert_bbox_to_z(bbox)) + self.score = score + + def predict(self): + """ + Advances the state vector and returns the predicted bounding box estimate. + """ + if((self.kf.x[6]+self.kf.x[2]) <= 0): + self.kf.x[6] *= 0.0 + self.kf.predict() + self.age += 1 + if(self.time_since_update > 0): + self.hit_streak = 0 + self.time_since_update += 1 + self.history.append(convert_x_to_bbox(self.kf.x)) + return self.history[-1] + + def get_state(self): + """ + Returns the current bounding box estimate. + """ + return convert_x_to_bbox(self.kf.x) + + +def associate_detections_to_trackers(detections, trackers, iou_threshold=0.3): + """ + Assigns detections to tracked object (both represented as bounding boxes) + + Returns 3 lists of matches, unmatched_detections and unmatched_trackers + """ + if(len(trackers) == 0): + return np.empty((0, 2), dtype=int), np.arange(len(detections)), np.empty((0, 5), dtype=int) + + iou_matrix = iou_batch(detections, trackers) + + if min(iou_matrix.shape) > 0: + a = (iou_matrix > iou_threshold).astype(np.int32) + if a.sum(1).max() == 1 and a.sum(0).max() == 1: + matched_indices = np.stack(np.where(a), axis=1) + else: + matched_indices = linear_assignment(-iou_matrix) + else: + matched_indices = np.empty(shape=(0, 2)) + + unmatched_detections = [] + for d, det in enumerate(detections): + if(d not in matched_indices[:, 0]): + unmatched_detections.append(d) + unmatched_trackers = [] + for t, trk in enumerate(trackers): + if(t not in matched_indices[:, 1]): + unmatched_trackers.append(t) + + # filter out matched with low IOU + matches = [] + for m in matched_indices: + if(iou_matrix[m[0], m[1]] < iou_threshold): + unmatched_detections.append(m[0]) + unmatched_trackers.append(m[1]) + else: + matches.append(m.reshape(1, 2)) + if(len(matches) == 0): + matches = np.empty((0, 2), dtype=int) + else: + matches = np.concatenate(matches, axis=0) + + return matches, np.array(unmatched_detections), np.array(unmatched_trackers) + + +class Sort(object): + def __init__(self, max_age=1, min_hits=3, iou_threshold=0.3): + """ + Sets key parameters for SORT + """ + self.max_age = max_age + self.min_hits = min_hits + self.iou_threshold = iou_threshold + self.trackers = [] + self.frame_count = 0 + + def update(self, dets=np.empty((0, 5))): + """ + Params: + dets - a numpy array of detections in the format [[x1,y1,x2,y2,score],[x1,y1,x2,y2,score],...] + Requires: this method must be called once for each frame even with empty detections (use np.empty((0, 5)) for frames without detections). + Returns the a similar array, where the last column is the object ID. + + NOTE: The number of objects returned may differ from the number of detections provided. + """ + self.frame_count += 1 + empty_dets = dets.shape[0] == 0 + + # get predicted locations from existing trackers. + trks = np.zeros((len(self.trackers), 5)) + to_del = [] + ret = [] + for t, trk in enumerate(trks): + pos = self.trackers[t].predict()[0] + trk[:] = [pos[0], pos[1], pos[2], pos[3], 0] + if np.any(np.isnan(pos)): + to_del.append(t) + trks = np.ma.compress_rows(np.ma.masked_invalid(trks)) + for t in reversed(to_del): + self.trackers.pop(t) + matched, unmatched_dets, unmatched_trks = associate_detections_to_trackers(dets, trks, self.iou_threshold) + + # update matched trackers with assigned detections + for m in matched: + self.trackers[m[1]].update(dets[m[0], :], dets[m[0], -1]) + + # create and initialise new trackers for unmatched detections + for i in unmatched_dets: + trk = KalmanBoxTracker(dets[i, :], dets[i, -1]) + self.trackers.append(trk) + + i = len(self.trackers) + unmatched = [] + for trk in reversed(self.trackers): + d = trk.get_state()[0] + if (trk.time_since_update < 1) and (trk.hit_streak >= self.min_hits or self.frame_count <= self.min_hits): + ret.append(np.concatenate((d, [trk.score, trk.id+1])).reshape(1, -1)) # +1 as MOT benchmark requires positive + i -= 1 + # remove dead tracklet + if(trk.time_since_update > self.max_age): + self.trackers.pop(i) + if empty_dets: + unmatched.append(np.concatenate((d, [trk.score, trk.id + 1])).reshape(1, -1)) + + if len(ret): + return np.concatenate(ret) + elif empty_dets: + return np.concatenate(unmatched) if len(unmatched) else np.empty((0, 6)) + return np.empty((0, 6)) diff --git a/easy_ViTPose/to_onnx.ipynb b/easy_ViTPose/to_onnx.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..a1889fb0881542561bd60db9861a2af6c961308c --- /dev/null +++ b/easy_ViTPose/to_onnx.ipynb @@ -0,0 +1,188 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import torch\n", + "\n", + "from vit_models.model import ViTPose\n", + "from configs.ViTPose_coco import model_small as model_cfg" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Torch to ONNX" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "================ Diagnostic Run torch.onnx.export version 2.0.1 ================\n", + "verbose: False, log level: Level.ERROR\n", + "======================= 0 NONE 0 NOTE 0 WARNING 0 ERROR ========================\n", + "\n", + ">>> Saved at: /Users/junkybyte/Documents/easy_ViTPose/easy_ViTPose/ckpts/vitpose-25-s.onnx\n" + ] + } + ], + "source": [ + "CKPT_PATH = \"ckpts/vitpose-25-s.pth\"\n", + "C, H, W = (3, 256, 192)\n", + "\n", + "model = ViTPose(model_cfg)\n", + "ckpt = torch.load(CKPT_PATH, map_location='cpu')\n", + "model.load_state_dict(ckpt)\n", + "model.eval()\n", + "\n", + "output_onnx = 'ckpts/vitpose-25-s.onnx'\n", + "input_names = [\"input_0\"]\n", + "output_names = [\"output_0\"]\n", + "\n", + "device = next(model.parameters()).device\n", + "inputs = torch.randn(1, C, H, W).to(device)\n", + "\n", + "dynamic_axes = {'input_0' : {0 : 'batch_size'},\n", + " 'output_0' : {0 : 'batch_size'}}\n", + "\n", + "torch_out = torch.onnx.export(model, inputs, output_onnx, export_params=True, verbose=False,\n", + " input_names=input_names, output_names=output_names, \n", + " opset_version=11, dynamic_axes = dynamic_axes)\n", + "print(f\">>> Saved at: {os.path.abspath(output_onnx)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Inference with ONNX" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ">>> Original image size: 798 X 720 (height X width)\n", + ">>> Resized image size: 256 X 192 (height X width)\n", + ">>> Scale change: 3.1171875, 3.75\n", + ">>> Output size: (1, 25, 64, 48) ---> 0.0390 sec. elapsed [ 25.6 fps]\n", + "\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "IMG_PATH = \"examples/img1.jpg\"\n", + "\n", + "import onnx\n", + "import onnxruntime\n", + "\n", + "import cv2\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "\n", + "from time import time\n", + "from PIL import Image\n", + "from torchvision.transforms import transforms\n", + "\n", + "from vit_utils.visualization import draw_points_and_skeleton, joints_dict\n", + "from vit_utils.dist_util import get_dist_info, init_dist\n", + "from vit_utils.top_down_eval import keypoints_from_heatmaps\n", + "\n", + "def to_numpy(tensor):\n", + " return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()\n", + "\n", + "ort_session = onnxruntime.InferenceSession(output_onnx)\n", + "\n", + "# Prepare input data\n", + "img = Image.open(IMG_PATH)\n", + "\n", + "org_w, org_h = img.size\n", + "print(f\">>> Original image size: {org_h} X {org_w} (height X width)\")\n", + "print(f\">>> Resized image size: {H} X {W} (height X width)\")\n", + "print(f\">>> Scale change: {org_h/H}, {org_w/W}\")\n", + "img_tensor = transforms.Compose (\n", + " [transforms.Resize((H, W)),\n", + " transforms.ToTensor()]\n", + ")(img).unsqueeze(0).to(device)\n", + "\n", + "\n", + "# Feed to model\n", + "tic = time()\n", + "ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(img_tensor)}\n", + "heatmaps = ort_session.run(None, ort_inputs)[0]\n", + "# heatmaps = vit_pose(img_tensor).detach().cpu().numpy() # N, 17, h/4, w/4\n", + "elapsed_time = time()-tic\n", + "print(f\">>> Output size: {heatmaps.shape} ---> {elapsed_time:.4f} sec. elapsed [{elapsed_time**-1: .1f} fps]\\n\") \n", + "\n", + "points, prob = keypoints_from_heatmaps(heatmaps=heatmaps, center=np.array([[org_w//2, org_h//2]]), scale=np.array([[org_w, org_h]]),\n", + " unbiased=True, use_udp=True)\n", + "points = np.concatenate([points[:, :, ::-1], prob], axis=2)\n", + "\n", + "# Visualization \n", + "for pid, point in enumerate(points):\n", + " img = draw_points_and_skeleton(np.array(img).copy(), point, joints_dict()['coco']['skeleton'], person_index=pid,\n", + " points_color_palette='gist_rainbow', skeleton_color_palette='jet',\n", + " points_palette_samples=10, confidence_threshold=0.4)\n", + " \n", + " plt.figure(figsize=(5,10))\n", + " plt.imshow(img)\n", + " plt.title(\"Result\")\n", + " plt.axis('off')\n", + " plt.show()\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.17" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/easy_ViTPose/to_trt.ipynb b/easy_ViTPose/to_trt.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..f7ef17c37e20c8fe527024706636962d1f338a34 --- /dev/null +++ b/easy_ViTPose/to_trt.ipynb @@ -0,0 +1,327 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import torch\n", + "import tensorrt as trt\n", + "import onnx\n", + "import onnxruntime\n", + "\n", + "from vit_models.model import ViTPose\n", + "from configs.ViTPose_coco import model_small as model_cfg" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ONNX to TRT" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "def export_engine(onnx, im, file, half, dynamic, workspace=4, verbose=False, prefix='Tensorrt'):\n", + " logger = trt.Logger(trt.Logger.INFO)\n", + " if verbose:\n", + " logger.min_severity = trt.Logger.Severity.VERBOSE\n", + "\n", + " builder = trt.Builder(logger)\n", + " config = builder.create_builder_config()\n", + " config.max_workspace_size = workspace * 1 << 30\n", + " # config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, workspace << 30) # fix TRT 8.4 deprecation notice\n", + "\n", + " flag = (1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))\n", + " network = builder.create_network(flag)\n", + " parser = trt.OnnxParser(network, logger)\n", + " if not parser.parse_from_file(str(onnx)):\n", + " raise RuntimeError(f'failed to load ONNX file: {onnx}')\n", + "\n", + " inputs = [network.get_input(i) for i in range(network.num_inputs)]\n", + " outputs = [network.get_output(i) for i in range(network.num_outputs)]\n", + " for inp in inputs:\n", + " print(f'{prefix} input \"{inp.name}\" with shape{inp.shape} {inp.dtype}')\n", + " for out in outputs:\n", + " print(f'{prefix} output \"{out.name}\" with shape{out.shape} {out.dtype}')\n", + "\n", + " if dynamic:\n", + " if im.shape[0] <= 1:\n", + " print(f'{prefix} WARNING ⚠️ --dynamic model requires maximum --batch-size argument')\n", + " profile = builder.create_optimization_profile()\n", + " for inp in inputs:\n", + " profile.set_shape(inp.name, (1, *im.shape[1:]), (max(1, im.shape[0] // 2), *im.shape[1:]), im.shape)\n", + " config.add_optimization_profile(profile)\n", + "\n", + " print(f'{prefix} building FP{16 if builder.platform_has_fast_fp16 and half else 32} engine')\n", + " if builder.platform_has_fast_fp16 and half:\n", + " config.set_flag(trt.BuilderFlag.FP16)\n", + " with builder.build_engine(network, config) as engine, open(file, 'wb') as t:\n", + " t.write(engine.serialize())\n", + " return True" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "ONNX_PATH = \"ckpts/vitpose-25-h_onnx/vitpose-25-h.onnx\"\n", + "TRT_PATH = ONNX_PATH.replace('.onnx', '.engine')\n", + "C, H, W = (3, 256, 192)\n", + "\n", + "input_names = [\"input_0\"]\n", + "output_names = [\"output_0\"]\n", + "\n", + "device = next(model.parameters()).device\n", + "inputs = torch.randn(1, C, H, W).to(device)\n", + "\n", + "dynamic_axes = {'input_0' : {0 : 'batch_size'},\n", + " 'output_0' : {0 : 'batch_size'}}" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[05/04/2023-11:25:45] [TRT] [I] The logger passed into createInferBuilder differs from one already provided for an existing builder, runtime, or refitter. Uses of the global logger, returned by nvinfer1::getLogger(), will return the existing value.\n", + "\n", + "[05/04/2023-11:25:45] [TRT] [I] [MemUsageChange] Init CUDA: CPU +0, GPU +0, now: CPU 4253, GPU 1346 (MiB)\n", + "[05/04/2023-11:25:45] [TRT] [I] ----------------------------------------------------------------\n", + "[05/04/2023-11:25:45] [TRT] [I] Input filename: ckpts/vitpose-25-h_onnx/vitpose-25-h.onnx\n", + "[05/04/2023-11:25:45] [TRT] [I] ONNX IR version: 0.0.6\n", + "[05/04/2023-11:25:45] [TRT] [I] Opset version: 11\n", + "[05/04/2023-11:25:45] [TRT] [I] Producer name: pytorch\n", + "[05/04/2023-11:25:45] [TRT] [I] Producer version: 1.12.1\n", + "[05/04/2023-11:25:45] [TRT] [I] Domain: \n", + "[05/04/2023-11:25:45] [TRT] [I] Model version: 0\n", + "[05/04/2023-11:25:45] [TRT] [I] Doc string: \n", + "[05/04/2023-11:25:45] [TRT] [I] ----------------------------------------------------------------\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/tmp/ipykernel_3056/1333021398.py:11: DeprecationWarning: Use set_memory_pool_limit instead.\n", + " config.max_workspace_size = workspace * 1 << 30\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tensorrt input \"input_0\" with shape(-1, 3, 256, 192) DataType.FLOAT\n", + "Tensorrt output \"output_0\" with shape(-1, 25, 64, 48) DataType.FLOAT\n", + "Tensorrt WARNING ⚠️ --dynamic model requires maximum --batch-size argument\n", + "Tensorrt building FP32 engine\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/tmp/ipykernel_3056/1333021398.py:38: DeprecationWarning: Use build_serialized_network instead.\n", + " with builder.build_engine(network, config) as engine, open(file, 'wb') as t:\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[05/04/2023-11:26:01] [TRT] [I] [MemUsageChange] Init cuBLAS/cuBLASLt: CPU +1, GPU +10, now: CPU 6720, GPU 1356 (MiB)\n", + "[05/04/2023-11:26:01] [TRT] [I] [MemUsageChange] Init cuDNN: CPU +0, GPU +8, now: CPU 6720, GPU 1364 (MiB)\n", + "[05/04/2023-11:26:01] [TRT] [I] Local timing cache in use. Profiling results in this builder pass will not be stored.\n", + "[05/04/2023-11:26:16] [TRT] [I] Detected 1 inputs and 1 output network tensors.\n", + "[05/04/2023-11:26:19] [TRT] [I] Total Host Persistent Memory: 6448\n", + "[05/04/2023-11:26:19] [TRT] [I] Total Device Persistent Memory: 1536\n", + "[05/04/2023-11:26:19] [TRT] [I] Total Scratch Memory: 13172736\n", + "[05/04/2023-11:26:19] [TRT] [I] [MemUsageStats] Peak memory usage of TRT CPU/GPU memory allocators: CPU 0 MiB, GPU 0 MiB\n", + "[05/04/2023-11:26:19] [TRT] [I] [BlockAssignment] Algorithm ShiftNTopDown took 0.031095ms to assign 3 blocks to 7 nodes requiring 17301504 bytes.\n", + "[05/04/2023-11:26:19] [TRT] [I] Total Activation Memory: 17301504\n", + "[05/04/2023-11:26:19] [TRT] [I] [MemUsageChange] Init cuBLAS/cuBLASLt: CPU +0, GPU +8, now: CPU 9123, GPU 3804 (MiB)\n", + "[05/04/2023-11:26:19] [TRT] [I] [MemUsageChange] TensorRT-managed allocation in building engine: CPU +0, GPU +0, now: CPU 0, GPU 0 (MiB)\n", + "[05/04/2023-11:26:21] [TRT] [W] The getMaxBatchSize() function should not be used with an engine built from a network created with NetworkDefinitionCreationFlag::kEXPLICIT_BATCH flag. This function will always return 1.\n", + "[05/04/2023-11:26:22] [TRT] [W] The getMaxBatchSize() function should not be used with an engine built from a network created with NetworkDefinitionCreationFlag::kEXPLICIT_BATCH flag. This function will always return 1.\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "export_engine(ONNX_PATH, inputs, TRT_PATH, False, True, verbose=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Inference with TRT model" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading cached TensorRT engine from ckpts/vitpose-25-b.engine\n", + "input_0\n", + "output_0\n" + ] + } + ], + "source": [ + "import cv2\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import pycuda.driver as cuda\n", + "import pycuda.autoinit\n", + "import utils_engine as engine_utils # TRT Engine creation/save/load utils\n", + "\n", + "from time import time\n", + "from PIL import Image\n", + "from torchvision.transforms import transforms\n", + "\n", + "from vit_utils.visualization import draw_points_and_skeleton, joints_dict\n", + "from vit_utils.dist_util import get_dist_info, init_dist\n", + "from vit_utils.top_down_eval import keypoints_from_heatmaps\n", + "\n", + "TRT_PATH = \"ckpts/vitpose-25-b.engine\"\n", + "\n", + "# SETUP TRT\n", + "logger = trt.Logger(trt.Logger.ERROR)\n", + "trt_runtime = trt.Runtime(logger)\n", + "\n", + "print(\"Loading cached TensorRT engine from {}\".format(TRT_PATH))\n", + "trt_engine = engine_utils.load_engine(trt_runtime, TRT_PATH)\n", + "\n", + "# This allocates memory for network inputs/outputs on both CPU and GPU\n", + "inputs, outputs, bindings, stream = engine_utils.allocate_buffers(trt_engine)\n", + "\n", + "# Execution context is needed for inference\n", + "context = trt_engine.create_execution_context()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ">>> Output size: (1, 25, 64, 48) ---> 0.0242 sec. elapsed [ 41.3 fps]\n", + "\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAASUAAAFTCAYAAAB/HBqrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOz9WdBtWXLfh/1y7X3O+cY737p1a67qrq7q6m6ggcYMYiAEkBRhiaRN0gpBks0QaUmOsB3hkB8kW2FFWA8OhR8cirCtkG2JocGiJMqWRAAUQBICQMyNRs9DzeOdx28+w14r/ZCZa+1zq7pKZEtiU7obqL73ft85e++1Vq7Mf/5zWKKqPLweXg+vh9d3y5X+Qb/Aw+vh9fB6eI2vh0rp4fXwenh9V10PldLD6+H18Pquuh4qpYfXw+vh9V11PVRKD6+H18Pru+p6qJQeXg+vh9d31fVQKT28/ju/ROTXReQv/4N+j4fXd+f1UCk9vBCRt0TkREQOReS6iPxVEdn57+jZ/3MR+a3/Lp718PqH43qolB5ecf1jqroDfBb4PuBf+gf7Og+v/6FeD5XSw2vtUtXrwK9gygkR+RER+R0RuS8iXxaRn47POsp5Q0QORORNEfkF//m/KiL//uhzz4iIikg/fpaIfBL4N4EfdZR2/7/t8T28vvuvh0rp4bV2icgTwD8KvCYijwO/BPxrwDngXwT+UxG5KCLbwL8B/KOqugv8GPClv5dnqeo3gX8e+F1V3VHVM/+NDeTh9Q/t9VApPbzi+s9E5AB4F7gJ/B+Bfwr4ZVX9ZVUtqvq3gD8E/rR/pwCfFpFNVb2mql//B/LmD6//Xl0PldLDK64/64jnp4EXgQvA08BfcNftvrtXfwy4rKpHwP8UQzrXROSXROTFfzCv/vD679P1UCk9vNYuVf0N4K8C/xcMNf17qnpm9N+2qv6f/bO/oqo/B1wGvgX8P/02R8DW6LaPftgj/5sew8PrH+7roVJ6eH3Q9X8Ffg74HeAfE5E/KSKdiGyIyE+LyBMicklE/oxzSwvgEHPnwLilnxSRp0TkNB8eybsBPCEi0//WRvPw+ofqeqiUHl7vu1T1FvDvAv9r4M8A/zJwC0NO/ztMbhLwvwWuAneBnwL+Bf/+3wL+I+ArwBeAX/yQx/0a8HXguojc/m9hOA+vf8guedjk7eH18Hp4fTddD5HSw+vh9fD6rroeKqWH18Pr4fVddT1USg+vh9fD67vqeqiUHl4Pr4fXd9X1UCk9vB5eD6/vqqv/sF9+4+1fVhBU7N9CAgpaPB1FEiKC/xoViGiegKXFif2hqqjaz8X/LWLftD8EEaEFA3X07/ZZVfEbqz1LIvtOENTfTfGvjb5n94hnjS/xcdR39+e2n7Wfx3M/KGpp92/vXEei1Ge//3sJ1QKiCKm+L0CKv4+/ooV4o3g/G23xMccMW9JQkoR6+pCo1nm254hbJaGo2nylVL+vMe82AP9eGr2T1nujYp+x1aorYs8DxO6ro9+CUlTrapRSRvcrlJxtFKmuKFogpb7KSZUd9TElIf7P1qpQtPiQhIQACZHO5kxzzGb8/wOyE/LjaycFkULOg41Ukn9bQDu/t5BS+65oLItUOVSXVftxsvvEnlBBKTbmEIGiSPLfjfaYiqKaKdpkX8TnRROxO8f7gLivCkpGKT5jXV1fmx8x2fR5rDLwgJyO92Mbm9L2g88vEp/kpad+Zn0Tjq4PVUr1Xv7coookqpJitIkR+IB9OlJIWhXSmhKQ9XermzoEomo3HQ0OStGRgrFJi81ZhVKwzS6gpVTlpbEBR8IQbzt+JZvkeLNECG98fl35yOj7LhWqmJA2BSu+OYU0mls1ySV+Z+NP0jFeAsGEE1H/eTJh1IwygLrgVlXTuao2wUoCkkLwfDyhDLWtSyxmnRdpc+Wq377r8xgKAxkp5bgf+PuJv1tbb9VMGmlckWwbRezeyTd80dyeQapy0GQIJDWBT+CaIF6x+De70fPt02PFU3+uTU5UCyLdaBOW+skYq0pBaAqprfV4Q0h7nsSahxDFXOuaUa7yVkJE1vdKVdQ6ujeCKVshxfMf+F615FLqe7j5WP+U769S1qyiz0Fq9xr96SJh5krVdqK6ORIZreO3vz5UKZU1wROz0tmtboMoqEmBa9WwsmKCUdyK+wZPKa2/mMa/kn/LJtQmsgmAaXNc2LQOviokbVa9WniA4jbHNT4p+ayJb4jYQanObVUs/l5hveJK4gIxErox+rBh6domFAz5mCVJQE9KruEFYOXvGEjFlEcSqeNEgeSKRAVVccFfgnRmKaV9dGylzLo5VtAOTabwQn01Cz0WzhhjjN+tYFX6Pq8GXzCFMf5e/B1bo+JKOdDcA8hTQ9y0GRlVpWipxkFEqyyNjVQTRhe52DxVKdmmQByZFq1I1BRPYLxATabwTcwLSZOhKpc/UEpRXz5DHOLr6mLt8hvrZ9MUylJ8sLG2Nq6wZcURcPHPj4ynxD1cCRdDk5pDjtWUDUJx9CgJ+zsxF64cNPaP7XUh++rL+hjqWjZPpu3hWN8RMNAw4E3JSkVmdeN+2+tDlVLOQxWWWMBSXbewqEJKDc6Vkl0p2KSLL3rxl+9SB9qNFMfgt+vrgtgmSSOEFdY+pkZGwh2WwgYdbgTSBXZBdWCMHsKiJ+n9PkBJ9efV7QBTVq6wbEO6ctMShqyuTd1oVeBiM8dWjnnzu5WYg0B5AqPFVspI2bEO71V9rot93wU51qdacZeKlJIJpma7R4lNJ21D0DXB8ecnEd/YTYXFhjEByy69ZfSebU4CzDYDkkdIx2emtJ8XLaiuULIrGHextJC6zlFuGb2LKTpND6AIzb45bZ4Q6Nz1srVIPj8FlZDTkK/2v1Qp8rmUmOsyQvS4+2hoT6Tz9Y85cQVSN6ivvcu1qpJSIqUeio0ZLWQdzACFwayCZjJqOk7bRldFpYw+22SnroWvW3FZCnlJjoRxxWhuqclTdQHDyPqi2rZzmSylylsYjPGeRds41l2/918fqpRWq2XdCLkuTLOkKXUIidUqm9UHcsmItM2UELM/WkClOVfuCrQJDyWSmyUNvqEqN1+Q1I2+l5rF80k3NObLIkqiI2u2exTbrCl1FDqHxKHk1BScL46quTx2H9P+xbG0Vis3vnRtwlVL5RbUv2fem1stzUjqXMDzaEzFhWPsDrhxqPcLy5RRsm08AhE25FbcbS1aqqqV5Ig0UE9FVO154taulLCEgqSEuYzZlEgoWi1mUKv8h5UMVGFj1uqSubJwAS5lxItodmU7jDaSO+ZqljzGH25KKLjGUYrP6apacRBySqz1mQv3LOYA3AA1vifJxJ4joYRsTKV6BWlkwuweSbp6/8b7BXcFKlLBR0U/2TidUqFIQRkczBS3d4G8m/KXQF50ruTHVlIrqgpFJuLGCx2tO2ScfxLDezpat5AjKSM+Ulypk025ukcU7wXO5dWp1jXw8mHXhyolMDIwtGVWs16SEsk3MeIu2cjPF5mQZGKf8bdM2IZM0hNEmYQFcU2vrm1tEhr0s4WzZxZVNBuxmSqCaajKSFCbxKLZ3RuhDLaWpZSKwoRSrYL470xIuzomTWpLJj1KoWRzsySFrx0Crb6G7p6quQIlKyQXzFJIndKlrn0+N/RlGzMslyFKoM5X7HFxC2XvO5DLQBCnJu2mbpLzF6XkkVIUXxvnScZzXNSBYfI7hJITv1+4aK4MA8VqQVzBoKCiQbs7+do2SrhJRZtLXd23UGSBEMO1lZgFB6Hg6+RIymfJ5j/+HiQ2dUPLIK6U3Hy5GxYItvJ8jtBMcSwIxwcRSEEXQCihThIpkJckILspjk1qaN2AVVOzFogYB0fCGDqCG5H+oKTUNZTi7752aUJkgoi6Anf59ne1Z7e1xV16u0/2/R4TXAj+M3Wxv2J/UxGeSJOtWOOY17FbnlIi549WSPBRSklnJHE3DgXtKBSzov7uwemaElGz5NKhkijujplSUQwEKYVielkcRcGYnrEFy2ZZ7DMl5tz+pkoqShFfyITD4RACqe/TNnAsNmYtRpZdggxXQx1JCnnw6AGdCalPftFsGy1rRR/mVoRC9Q0jUv392NSqBXKzqusbYeQa+hWfKxVSh0VipJCbRSpl9P2wrgkXGlNOY+7LUE+piDyE1r9UXcuw3ik1BGluQPb5NuXc4CmjuQglomvCDCDOFY2jmS0Cmt4H94PeavOpaAkMPxZ4qesA43U25RKBkLY5nXvyF27zwwjBRsDE3UF/R1Uo0pFcoVDtsNZnhlJq7+iKVITArw6XCEFXd8lxdGNL6rKkjSur+6vOWa4yH+PHDWiS6uO4AgvkFngve1ABYu8JIEUgops0DspQIUjI4Bpv1dY1UNJ/3Trbj1BKNphSXFGEIsJhP5BkvCFCiBTchavoI9mkZecDCoqkhLNNrpTcDx+5FKFpY/JwVFJQRAeXfI/yoOQytM0rkLNpo5zbZMeEmR8fBGIZoQZHAWEV3NKAuactUlJsnK6c2iVVkGuahIw2pgZHlyoqtKvUjVhD/RrC3yyjuVFNQKqrFkg2wu/qBGoV0IaibBt0QDdCubFFLQhgSKtB8JypG2VsCStSfEDoQleVNrEYghmrEEcepSkfHL2GxYu1TeFi+EgK2Y2R1p+b/CXnomL+4nc2RqE3GRb3AqSF4EVDNrr2yjHz6nGSutFC+SqFzpT5sO6qxVpWA+t7qOtS5Y9CVuz/2zyGkc8RLCKjmizS6ApZ0LX1g8HlJZQaRhGghuLE2Cgh4Xw/pEiVgKIrW1MPXokGFeIunBuwoG7xYEvRjJTmNYX8Nu/KDd5obr/d9eEpAcVhoKrlQ+CQ0t9IfQM0K6t1kWJjSrJJNosTGwH/+apOXCyCqm1kI/Cq+ANKzrEB8Y2cq/Vv1jPXBaYqNvucWYt4jsHS+l1XMHWThGDE+NS4rJYH5MKnQ+UXqoJzRdp1vUXJGKGjKuT2E1Pa/sMYV6AMhzDBY8UlEWzw+a75TH4TrQhkFP0ZW1aC9zAk5N+q/BGYzW5rOZKJESozAlmrDFDlIIj4ZjHX+Yb1lY1/S0UpVOM0jrAZEGnuz4h6NA7IFVgJV6l+/4HLif3Ky2m7Z7xvzsPIZZY6tlLw9BLfjKPUlC51lZhvblNs4oSWBGIcjKGK1HgXd6VjeiL4kHO2lIMwbmTKyA0ajy/mORBzVUqhmFNTFvg+KShkIauQxBR9UeOPksja3JgBiNd1oxHGTLMr9NRE1T8c9zPF/ED0/QOuD1VKopmiq7q50cFhqE2iiDAMFv3xaQESUiKM7uhKbfOm1CHSjxY0MyaM19FGQFJPlvNJaW6LUsrKBcC0cKkWTEaLZPA3l2yWibZxcjH3zHgG42ceXGRNJim9JNDOJzyieQpiFjPn7FGkNgJTmJ6op6luhiaATSk0UngUxpfkhGsbjynlpjgjJ6q9t6OX+h2fWbfCce/mRvlzsM0niKO77PlCjedrc9r+U094jN9HwCOUT1lToOGsO9IOXjLW28dRg9IaN1K/7yjXTMZJmA2X2E9d/gSkItu27rY5prYxJY0MmeGxePdQXKHzK0KuTwwkrXRdfKjU31WECI3XiUSUEujS0agqxTcumGJtFmysRKnKktH4XeJ8nMq6MlY3Elr/bp9Lvp8VNDXyIAwhAYvi9p64614GIhFcrusVPF6sbcy4TYk+IBMffH2oUjpZ3mbQVSOYQ7s6/hYX9soruay2iFHLT0LVs4Ujh6Fp+eoCxKZLzrXgoWy3WmD5FkFuBjy3FVpRSialnpa1YDOWi4WUy2gy7fe+YGRKGQzau6sUsJ5i4ywiSLFEuvEYSnEuSIM4HUUo6sajRpp8wIF9R8ghiHkqoDIEIIh0a3NUM53bkrcNo2EppVrwcXZxQwemvKVGitr7BAltaMXu+75w/wP8V8z3g5uhrrUrcJMd34xryoIH/h7zt25g7DO6hkIqGoyAAKa+0tqGjffBUfGKSvSLufkhD+ubvn2vvYfPQIloID6ngxlxN87VaBBqWIHOFD1KS6rNhkik8UgPPmv977I2101pgiGlNq9NLpR1GVBIYYipfNNYhom0hQfeY7wm42mStft7RF61UjM23w2ZfrvrQ5XSkOeexi6V7BRxPgg87V2rel23KM0tqpa4qIej2zDa5I1zGrAFqhPtUYH2FSJ61qx/m6y1sKNra1unyJh2HicB5Kpsq4UsuAXrDPp2BjnNPYuUBdx1iGVpzx5nbWtZJwgh0ESYoAgvF3eVxd2xdl8lrJqPVbQiErM8Wt2spujHXFDb3GOFFUJcAw6BMktxkr4lLq4rh4YXJP6ngRAYCXKqUUqXidEaif8ZCbVV4OtSKxrufkQVtT6Vlnhqz2lL4TxUMeohpVDqVNdfdUXj3lpypslRFZ3R2pX3Kd2GXMXnqnFJRcvIbIiX+OTKB7Hmnlb8Rhi8iqjthdvcj1xlG3Op8h+fae8YaR3t3SvO84CTKce2p9UHLiKV+B+ve1vuNvfxm/VAQZvP+mesnX4HSMlkyNwOyU0wIw1RS2lpEOqbURi5T6VunqowRn8fT+T7rWxwVb1vyPy+iTFrlKt1tOeMlZPrTBWviUqeeWwp+OsLSH1nJQhBj0R5Jm4jrxWD28MavK8RI22Ro/HYx9EIE7wg1B1t+ZwUJ2+bInS7H8/XgVKJ4Q+2OioNsaKjtVuLgjRkFcrUXq1QM9Nc6+iDwqYj2fDPrJXOrLmclmbxQTkq8Y7tu7Fx2jYN5T12I9e4QN9YY7mqEhEGQiDcP5VkgfG6dm1Tt3UaP0c/AH2M5z+NXJIYj92nqRBb46LO49SyovGzmzEKtzCUdeUNI3HuAcQRCDiehDakvA4WIHKt7FapzrZIsj7H7vpq/J2WNC3J1ilcbNUaa6vv2cyttk0oLSn3A8Rg7fpQpVQzaKVFHfAXbVGreGYaWe9YvKpo16xKFf6RC7DuygWSCKFt9xkLhT1vbGEbQhtvVhG8XOP91m787PpvLJ8nXC5REB1bnAGjght/YJuir5tLqvC0dxmTxDZV4Wi08YVgRhSmupH+2TZf1L/HPMRYLHoSgW+ztk0xjvk/H2113Yb1tarzl9Z/vuZilZiBkcJo0T/7Xn7fHDdEOVbabX0fdBOMmB9Z+pHrMr61bWRxkNHub4B+bAybMhjLRMjfGHm9TyE/MI42r41jEhG68bwH+nGUhGoVUaMdHpgzl3vRZkjGaCe2fijV989vvIePQaAIpBG1IYHC/d9JmkcQ7zweZ0S/61rF9/x9dKRwmoSIZ9u7SlqrY/zg68OJ7jqhuJC7MOj7F2osrG2hwprZ0CNS0VyNZolgbMUdPSjO9Yw4lTqhaSR4WotX7YooWGjnQGnSJhNFsdwRQ8gtC139c4w4Hv+Bu7FNGYUwiXS0rFolks9U2kYiOITIdZFQ6qGIfTkd+uOfNRdnPOfhyo2Fb8TJOWINS5XEJHIM9auAS7V5D6xlemA9Yv0+AJ2NDMkYiYVbXkPeVZqavLS9pK4ItK5rKF4LIY/XUKvb2BRqS/ZrmJzR+/e+KVbU3LERf7M+9vb3RkU8qAx9HkY1clXlachGU1IN7WndR/a6KQoI6vJHFn6glFajp+ORrStKGY+8/TyUq6JrY4t9YXPduM8HPZuQsTVFpaGbRgY+0FOVw5a2IiIeQQbLg/sOlBJryxsDiHDw+/1CVaXrOhfgwoMtQcYIZ2x1cwbIa1bSnhcLWRhzD5Dcfw2itimIhiAcYWhYWpv44tIjQVCPkY67SB2RP7UCHQz1SHt/u4FnBkvXinzRqsDsPYfR+7jZIzliY7QB466pGQBNddyS1hXGOBdkLOzx+4a2wpUwa2UgSWsCpkJ1ReUBhZI8ryTWIBTj+xFDm/9aRx3Yn3VlCWMXTNbWuOrtkKW66fr269HGD5cBV9Ks8UJ48Ws8MwzJesTvQaP6QVfM8fqcx5v6zqi8WeTYpbquY7L5QcWvqKW+iCGIQBuIJRdTdOQNjFJHoApNU1TrBnj8LIhwf8xZ+1QkxMbHx3LUDMcIrY+AduPHRgqJhrqa4h/9Xtbf7IOuD1VKXdevKR8jQhNW2xahv0BH65yB5fT426v5+GEZ112oZt0tGzz5c96fYFWVldfQiDYk0arr2yZ6cHKrS1Ilu6MQpShUQbJ1U8s7L+ucRbybKbhmqSVRa4Ys3aFFHpvlcGcnBclLUzwjy6QipOJ8Fs0qjccznnsfDNFlwMbQ8sdkbVM3iUwjBRaKIpRebOBAICmlWvoT77OGzupbYBn7VSGMC3XX16bKiiPfUJVtczUXA1XL9fH39nRAopLe5A9atf249Mme27mirckEgRo+wD2LzWjjHhgbUf8ErbfUyDCIJUaaPWzpFCJpPSetjrvhVBnNT6UBRnslFFkzKdIQzPtQ9Og5ncWyO7SmuKyBhQfQ6/oaSZvLsK0PKPPkYwsQ0OSzKcmmvBIPTPX7ro/klFLnvnxpwmhhxzQahCkK1lwKPEfJQ5/jQVTtH5MLa368JBLdaPLjnoY0UrJCWg1d5Pdq85bW7lsXXcYmQlHtTOCqFW2EaO+p+DmtK424QZJkGek64n0esKQR1TEYb7+vCriOLVBknSDbeJ73UqN3lVAez0U8xxVhda1pkVEJbkLpxFBakchnkfeNbY0r8KhVcAVd1wReRgozpVQLm0MxU5uPhWkU59GkKnURajlRGKNqVpQ1NyTkwne7lzeYUo8IkqmBjKpziI6Gx5vDNq27VlgJT6pyEQpCHe2a4S0lqunHCMvkELVCYcEKvsXnXhCvvG/yKUkqSq37JpCz9lY/5+g9+eZVX8NY7+xFyaEMhMa5Nl6qSpW53MlUu2enkYhs9VGuWxM/YiYiQVLEXcqYA7U5KqXU2r1QjiYz9uxAilVG6+p++PXhSClNiUQsbRw2gnks0e6gRYVGpRzFBKCMNoYhJsvyLhrZxYJ00Uugc03aVeUWaAJpm18CFYVfTmxqoblkgIYd8vdOpkjEezWpKllNy6fqXoX2tcZnibElN6UoqENXL1lOD2YrWzKlFQeHUrNQdCdiLSrWFmjsfjXLZ0VJkQjYyHxFPVWjkPyZ9mY8YCWNi4n2I7j1L2lYU0hmCYVxNTmOijXmP1wICtHd0S6XgeCDwihRRomq9jlD2bHG9qwuaVu7EQnfDH0UUI82siuQJKmmU1QEjlaZUS9xYmT9TXaMxxESETVu+MxRDwWw9SslNfdMBAtoiKMG0JLJZcC4QHPHupQeKLYtqKZRLp+tj4jQRdQslKi/27h2T93Ad/SsI1r8312tVogvjWUh1rATRyv+8jYzhZyj4gK65C19XJkUlCQ5qkSIKFqpCm0ETkL16brh82WtaOrDrg9VSn03Je5QqkUSUg3vJt/M5tOrt0UwEi+WOATYPgPFFg1qdTuewCfOEYWFbgvibkAqIV9EAzRERglfLcRNTH7le6yau5POXIwYj3ao81kSmx2tymvsSvhdaFyX/denaOylrnxytRKqXXUDzDsVUppgWj5CIfo++BsbtSkpjwYrhnQEIrVfkMrlWGlQZKYLay1O3RInnbirbFyDuRZakZzJk5XhFNW6qeyhuerTSizH+1YOM8bjfJOEQuiQNPXnQEseVIqOw/ttE/oEEcqoCrknEHZ4ciyjtBJVSD2axuU5tmaG0joCFVXZpOptX4/BCWcl9X1tzWFjji4SbgClo+sMdRdHfb0r6tq3KVBxtLMViABO5a06R9eppbiEwlX1qG28e6IqPesR1tVAQQhM1P9JjZwXvIrdAkMViSldGs2RdHVtbe9nVHtHps1NjRmMwFDjikPzjtcw0Nc4uPHB10cgJZu0JFDUuZ6AdME7eE6PYaDk7oNvZBVS15mSiJ+51jQE0VctWr+iwfsIXSTVeYe/xpeItYvoJq6U8qjPUSGl1kpVxNo9iEbWqnjnyM7cy5LR1CNRkCtCdO5LI9RiwQP1jRxV3GMkgEenEl03QhXxPWJDNdfFIkLqpST+mRr98GX0dygl102UIsHOUUotHnWEkEtqfdTpvA2KfztRleQYdXSxNCpoilytKpbUNiBRoOmyEBax6615nhYT0y6NAr8y/otvVmk8Y7x7KY1UVTXXoyaaRpV6fafmbqdxhnPdNFJlYp1PNKTE2u8CjYZyci4pe1sOwVvYNLSWUov2RvFrF43qMAMISpd60OT9vCIs7rOxFpWMaz23KaSnFEU7qHWlsfYVhJgRqfIKzlHZfAXSw/t8p0CfrggjIlZxbfWAvCNAKdRwvoaCaS14bGojz80NC2Gom1ewzid/8PXhnJI4v+E3VUC6cS6S+7SBitT3NQ0OqzrpmWziauqlk9ThnrSOiT4oH3iSREmRY9Sg7JrPS7GNGht5LMQ+EUhTINZh1JIiNQXUZ9SEqtTPq5dDpF7X3jEI2BDSpqxgXJtW3S7cgNeeOD6HmBJobV4fCO371XWtD5BrBeuMK+ESmWEoWLdCrWFX33TekM8W1t3oMbSmWU112C6jPllI/4A70DBwm+NUN0b8rHVoVEdYUd5iG1LCkDlSyHXDKCmpI12X8DGvNlpjIWAkUJpSip7Whu7DTa3TUscSyb517hFTDZExjRoKjDVx2NowdOc9x8y1GisrUxwdndr6lZJbBZ8EamkRwbhjdKRq5TTOJVU91jq+PkjCVyp8lEaSohg3KBTpnIhwl3GsHJN4fpQ09JyS1+tJ/b+KLO1LTZXWetRRh4jReEci94HXh6cEJIFc7bzzjM21iFUJt4U6JaHNRzkWjHmZ0aLEwqQxiSq+6E4KVxetRcGSpNodMdF5G1CFWpbQBH8M4CuQjrqlikiqCcY1aNWA1SJXMtb74FSlHcoxVWFqhJ/fD/Uq+LBmpT6vuWphUVzRfZurui8pNrDUdw7kVFvCSCA+QybB1Y1lcD3y1AxQjZxJRB3Xe+KYLLR8lLDg65fvIlc8738WdY1rB4pAoNXtaLOyvgGbkKtGsGOUB+TBk6rAwr8U25hjJTs2YKU0N1KkM1lUC/enrqsKpCISceJczSAXzW65AvWucy9Ctd5tpaUZbFAPEIyjyM0FJ5Cf2GfHScsPXqm+g3j6R6xuRukcAITf3fZmiN94uUy5B4kb7qN9OMrGxRFvyE1zAkd/+U7cN8OLwclEy4XUJpUQtJGij4HoWIERP6gvJ5JqjsZ40DV87q5EFTwa7KtRBzB3zz87RhrtvcY24AMSyOK10kjJVG1BnfQ6sMpfUTeBKSRzSQgSN5rM+4YAgVRqG4nsLUrCP4+rJSg+eFVMUudC3BWJ0L5Ia0RSs/Fd7MU5A6nkfwh2e1aN2CFI7aP0/k27vs6pzlgLCAAexECM3NdxwTEjpVFbqLgFJ4xPWFrqJrR3GUc6Ga0lVTY01q7OVmzouMf6riji+EYjn22MbC2FIHkeG8UxqUCJanylzWkYIEKRhCsfaQtCcndJdTy2+K+Aloa6Vd04N/fT9vt62P9BY2FTYJMg2hSJra4p5rrWFTHFGlpwJDykAGfjFIi4t46eGetSXVxZU0kf6bbF9REFucvmWwZBF9xCWHbF3TABLZUHMMtirWlVC6kLxJOr0qAufhP8msTIuuiYm9h8fgKpqKMOHnQt7OdB5lWFFj24CYJucAvQFOuan1yFvlkTrYgjSEsFRyyCuQ1FI4IzVieh11pkQutAfVOMxlwjcFUoR4iI9jt72zJ6kAnHgxZ0jEylCshYMUWrs9HYHnifB5FONUAR0fE3UlFPfNdahxc8BuLcZCBuhwwieOX0uKmdj9+7MQZqq4gj3kO1GiB7f18rTVj3MVpjBbyWMhYEvO2MHU7Q3OZx1X4izjks2pqrRacA6z5ha259iKJlrsu2E94Sf/eMLvtQT7ygfWWszGyOZSwDvgRjYvtBQ1ZcsccUt1701PUvsW+kRXSTdA/kc/med3feRvR+5W6gbf0ZIGjtoxTKr7xPrh68PqLJWyFrprjyGcPGyo9gRDSR+xFIRTHBdGEzJeEnX6w1x6pPQ9VLG8iMcxCK956OJMDqJyOjVhjU/kyhqbXkmmhp41FUIsqTzNJRnauGrtaKL8WtWvjjgW6Cn5AqfPF+EdlDbMxaoza4hdcYsT9LG7qIQ/w8Bwr1pFLF2+82yFw3hcQmDA6kxJT670aKxzeZ1vYhwFgVKtZUjKbM63xWpDo6vLJqpTZHFWj6563Wz4Qgxlu8D5W1+jA0KWsujH3faMdQdkKLWsb76NqzAn1UXsXnLMBBVZvqcx/CaV+rPbDaPYO0jeOHojgcmtLyPJ46H1KfbUGFERKScdqKMzq6qhs91ne9vcd4bIxkoF1VAY3kNMbUGrm0eSl+fmBcyQ1klfmauu1zuGakHJXXFtgRSPHnyfq7VxkKdPadlJmY4TI42U6hFHeZ0qjroy1wVgjOJ7rRNWbffXGhJmEZreIv61o0IlgRprdJsQZt4V6Ij94bjti7qkIJpZfqRFNKJWy1FEqdkCiD8YW0L9TNNppSn4x13DbmNsKex32LDlRoq+FGuiDrKHAQ5R4G9xoS9TPc7J7WTjQgPHXztd7U4TpUUtbvHYmjQuMWXK1QXU/fWPbZLqzH6LQOqsJQ83OMr1JFk7d28RB6pb2rrmgKJudcI38WyUuegGv5XDZJLmMj0r/+nyMce72Y7XHy3wgxSDNeSesKMm5G5xrED1sIPiSN5Has8OJ3wdPFONr6xX+Wzd2NWhzj8+goLxRD1ESqOKoZy5t9Xll3A2N8dc+toaRAzS1psZk+U4yBBkWE1Nk82jDHvoGOlMpIGY5RUfVQ4h0kptPWfHQARoDzQEhra/Btrg8/9y36uFTXwTZDkIRh2RoS8kH3VvyYBDskT5XCypdHGtpxNNXI0fXtHYIREFRHn0LDyuS6WVvDcjt7q24r1UpeamTEmnask6lebxaaoy5ElZZm/fBku/iyuQ5236KlWltlLDSlNp+L54/HI46sGt/TrHUIWAQURtuFgvVbTpoie9LmM4VIu0KrG3nEmbTfggoq0e0w3NMxCvFIT3GoD545EWs27qpgcrGmuLWt53pJTKQV2DtVTmj0b7S9q09onS/GP8fnStpmq4ceSFqLeo15o6qYpKy/pwTS6ohSC4lz3whEHGAr1U3ZOjyaNxFjCMSvnn5SvQXV9n4VbTpyinSFQFIm0CMUa8+MgwDWFDSjPUGp42mo1LGThBzEfmxXpUYYn2ajo3eJ5xUYdXJQ7+oZy9Oe36T3210fUWayXlALAdki1FkpMJ8E/7M08vv9sK9RgqQ4zYH68/jMuOauKtYRNIzQZnIhKhQPgzsETi3PCFHLIq/NslyIkHpP0YzmxqcQdkqbwIMJsGXcVk1cFcbY7RPcFXD/vORQXNjptOIdBFz5Vf4pKuLrZh4p6gcNjCtEMD7AlGpEAkeXGWTnOkYWL/7Xf6SRGFnHuw7562ZRF2eNufI5lkjNMF5wfDCmjF2q+gZ+qqwKWS3bOLiQRuyOlYNvTolBRWAjLHLLVRJ4f7QwNAi8793awLW5IH7jJO2f4bIo1NIq4xG9I6lCO2BVrDm/GxuRzmX0/eUdpZRx70BTAl3X2uhKuHWuAEboqonDeH1DMToirEpsHfEwAhzx+SLtlBqpaCgMIPV39ZmeEC2j9A/bPcWpHbfp3uN7nCbwQdeHZ3RPJqPxeTOwLlVhMKFpK1ZDyLE21bCNhWPUP5k4gtIHOeJ/ui6yXcdFjQ+Sr1oPJogoUEvsGPEyAB75qEI7OlHVXj8ycCve9M83nio8u+g4EBBeA22EdfUxmFtiG6p49jWucK0nlbSq+jpdMkKmgaiEOB1GDOAREziuQWMk6A0J6NrfR8tSbZwkMaXp7xHuhGB9zBMdZfCeRpEUKTSkmZpxsn7n9t6dJ87WjS/JO1maorZneclSRa72O6teT9iBjIGKtMFEiTE2ZBBKKNpkxHqP5yQCH1Lnb4wgTQ5C4WkMNHqsEzZM7PRaVzRRS2ZvqK6gmhza6cReglVd7LFCl7ph4yEyWrtqC3T0gXieNuW0FujxsXUyctXVJrsFJRqSsT8KjBRS3Xu07z/ofkWOn9k2Gb2PraXNR7y78Z3fEdGdUqpHFUW9EGUk0jUJzpBanLKgpViezlohpCcn1tNrXYhpwhMtagXx45y0bvzoJT2eEGkOGjVL2bmvsMwSxVg0dGTyFYRv3M15MxGMtLdvxILWPjM1yzwiJzbjdbNpbOxiR5SjlaBuRB8jhRICut6HOxBWtY4yipyMQoVjhZ+6QDHJlV8kKlLf00blmyhRozJdZ9EWU57CfD6wPBnQVY+UKSV3HBwc0E8zFy5t0k3tHc0ziftGQl3MQ0RsipVQgG/ukZLw+Uga94mNJQFE6/1NtjzIUfN2TI6KBtls94h6v4quXOYi6aD+eGSAmmi5QRh1HIh+Q2bpW29uG2Vu4W9v0auIn7Dic79mNIIfjPdTRt61LVXNewo5FpfH9Q1d3XxcvDyi53iM7gEjZWM1FNxCv+Fylbbf1+Yivup1hJ4WFIEIiCikv3tgL/E5bFoP60Oe+bDrI4huaWdMhR0Vv7e0qEigj65rvjyU0e9BNI1ctFgM2vexWdVa1QzGw/ihATquq4k1Lp7VOvZzXTgcoUTo3JYh1Qr1GhnCXKdSlE4NuWl1NWLj+6Q3j3IEpcdbxqMSqpbZXK2bh6X9xSO6ZnV0pQpi+PdxxwfdrTVXZKycxwiwmlRxa2lCVkqD3lKyGY0iTvzZfKzykpPlnPfevsIrL1/htZffgzyh044zp87w/Mc/zrmLp5nPD3nyufN0SWr9YbWQkl1OrEG+JSpWU7723jGPldStGy/myvmbEkW18Z1GoLuEjX69Pkdjwjc2tYhQUmAFWV9BaXcdb8jI5FnHms1wGlJtOVf2JSUy5GMd7M375gqPjUUgbBvR6PE6CioFigmDX0ajCJltrXLzB+S9hQsYXK7t70xECys6wmn5US2bKZ3sZSeKSrS0WRFdFcwoWtPDqjtincv6cd4fdH1EkzefW4GW5WoDNMsKIRDqkBlkHc57N0ZktKmq5R8dQ+PwUKQdzlijS+GzjDbpg+7cGqSUsKAuMFGUO47quOIx0GEwnHBF/c3HXBjgG9iVoUSuCVVZB+rrks+BCCXntaZt8a6m2Bv5txYV0hh9Q4IjUX/fteaieX9vlNqcLsZT1zIUsgKDcUHzkwVDXvGVr3yT3/utL/P1r7zF3Tv7zGYzzp85y+7uFqfPbvDc85dJkwmrZaGfeHmLji2xUMSNQXXTwmDIKIdHWQfS64QuVbbUd3Iot/b7VkkzNnFjmTAF1oqKR/Ibnxvt1zEfE25TvHvRkTys7fEWTgi2RFwJBdIaRwjrKEZu4xgFd7XkxLukjwDBg0apuXTqNfGN/8HN8AMvW59p4xsIlGQ9ozKVpAZHOanuS5v2bBHtCIJUdeiRdsQOB0mB2BqPO5b/D7s+IqO7VPgYdXCKtWWAtaT49Qe5tCUv/jOwor6hxxEZH1gpHzB348ULaxYKyr+ngYyoQpQC6fjLmvC3vBs7gw2KJ00GhA9Rz+O2uCNk1l7LkEVVRxrdIT05Lim1Wb1CJ1YC08SRKqAxe+H+Vb9fdU2edPzoqA2LEOsD8xkoJeAzYEKkicVy4PhoSc4dV65c48aN+2zOep548gKvvfo6n/+Dr/Day29ytL9kY3OHnc1dLj5yjtOndjh7dofp5pQvf/0rvPTSx8j3F+Rhi82dCf00vX9co7UZE7vjnLBqgeurxvyMAihVZhQ1VULRQi9di9QV/x83RoHeGrneIkXxHl1s+jWUJTXHcg2h+njGPzCKYdTd1JVSdEYYpwyEyEa+WXxOqroZdxzwt9C23a1YPHhMaj+yyItbn+8WccQj5YyVI+FG0xCeK5VSe7QHtyQIvRtshVqQa7l34yoK25tWpdFSfKJ7Q/BajNbi218fkRKwqgNtBaZidTl1i5lmbeRlI+aiO4CFx6VqU0vX17ppFHWKx+GkuCqMaFUgsFEtW1TBB6wNKDrkUpv+20IX8tA2bpEVyevkRFMt5HyQQB+f7romXCNlEkfqiPlHnvgZgQBFveg4Nl+E1ps1j1NY7V1jvlLkhPmzo5TGMnizZ4u394y5FhfoTszX1xzPhds3D3j37Ru8/eYtbtw44NbtPa5ducmkE7SccOvmLaazCZsbW0wmysnREWdOn+GF51/gjTdf5ZlnnuTi2UsshwV52bGxscGwyty+eZcLl86QeqlrbX2OwA5XGPFioSAS1LPOaIYnZHU8Xy3QALV3OUou1hmUMJaVbR2R2OkB56yBUHcYw7p3dU2MeHd1UGU+EU3Xoi0OIk32NNCnkDqPMGlwjtRxoi3I07outJA7CES0ikg9UHcSUi1RKqWsZZXbHKZqz0w2B6LbBcMYDuaYCntfl2lDSgEO1FCUCikCLNHGRw1BWcJnQF2pxtq8nwKsoLYysmcZEFB03JztA64PVUqrYT7yY0cCpC064yLiE5la+wLR2r6hvnglrcOXpQqswdRWuS4+UZHvU1SR4jzMCFZD9JlJ9TlxVLblkTx4Qqop2pR6hK62FhEeQG9VSTUrL2mdm8klj6q2Ae0QCngPpbBGitfB+eIgyVqmUIiTcyMqY4ZGSF3v420tUVpZQbgRhZJb8h+CRcqirUYxlfmtV9/g1vVjnnr8CUp5jyvvvMP1a7dZzOcsVnM2plOOjo64e+eI6Dow6TqGVeELf/glptMp/+Uv/QZ/+Ftf4vHHH+WJp5/gY594mo+98BTb2xc4OjxiYys4xvVui82ym4EQ3+Cm82OusY0vwQ+2kD2ebBm0Uox/ILjHBifjoIqq5Op34lmp/nvMGgqtdEpVkRJGzSoCKJaykBx5ZXffSykPyI2YTBgsr8ebGXATt8N+mKooSTsiABLdNDKGNJTs/nUYeYsuRz5ULiuUIQbjbqrvJQbsgATCkjZvQPOaqxvUS3g7tRNoKB+fsETvclusRIXcmrzVSbZoX02cpEOJAzrbnpBRtPKDrg9VSsvlwojktg38YdBON2nooUJUbD6zL0ac827uiTiigMjetc8X/7e7VC58cTpvuyLfoG3ENgnW1TEiNKbMShWYVDV3JqVMF722fQGgIa9af1SJdUGGKB8RP5GkmOC7ZdYcliaUsKO92DdVuAQt0QMKauZGFPQilCHXBQ8UlNQa4JUShx6WmjfT1ib6Q/f0IqzywK/86q8zHG7xG8e/zfHhgjPbF3ns0nkm0wlf+vJXuLV3n+OjY5Io/WRi/aCkY8grDg4OuHjhDI9cOs+Tjz/G1mzK7es3OXfmDFc37qGpcPr8hDMXeja23crUeg7fmLmhzJQEKQkNjk2lbojugR5FddKIEhuaJEp2ox9zXT9K13V1zWwzSjWUtWDYa9Yic2btkIuRu5M0egQFp2k/rwoxXO5AC9Q/XEkUapWJfzQQUKoFyT5eVSvx8bmrPcKgeQMaiZaZtWPmK2dlPx8fjAktqlvFDKmdNWq7YMMNVUFCcUowg0xI3j46pY6sC5+SAql3ZSPkUPoSAaWlGWBffy1Ckgkfdn04UsorUglNO1IMo15F6tKwlnPhMLidxtAWSuj8fHdfSEZ5EW7NtDIPrtS0oRXr/RKrbAS1LXS23J9RXhEiZPXSFQSpmcNKzkJJ4UpEhnEoQkFLqvJurUmMb1IfTNaynltCILFAloGEqOjPVjjX31uHSEeQYnPcClWpLmnMvABdZwtaSpSZKMPg1i+B0kEe0KxcvXabv/7X/za/+xuvkRfKtO+YTSf82I9eZPvcLt/81je5fes6y9XKGuqlDh2gaEdKmcnmBhubUx65dImvfu3rzBdzHnv0MhfPneP8+Quc2t2lm0xYzI+5dWUF/T4XH9+lm6jLS6kZ4IxGYjlIXVvLGoCgjq0h5q4qZqoyYGRs/M4j8ZTBJiP6DY15lLjWOqmODYmjB0bEtgg1AhiuNv4ZN1fU1h+Vn7Sfr3dGoPW5lnghrTKe1IxgZFjXaFhVHPE0V+hSvDtmHAXmSqlE/WOQ5OPqAJpMJqoSDsNq2sMRFCvINu89u0jaYlEO0JzNI3DDKLn3NZS1PRBkuqk39fka9fX6NtdHdAlozdADATUYOGL6R65cLLy6Fck5QsTxwiO3K5BEQFD7qaujUHaJ2hQfXbuH/W5SrZ1q8qJcV4Lu90dTei3rhyJaH+1QIiEs8QzvNYPUDNeAwfGW9vvxmCHyZoK1CIUdfXiaoEW+hiM65yoKxfsuASm1REDfALlu2ETJpZa12AvY3K0WK379177A3/hPP8/1K3eYn5xQivDohYt8+sUXePPNt3jvvffYPzyg7yZMeu/lnVKN2A1lYLlaMl90vPHmW8xmU15/6y3u3T/gmaef4tTp01y7dp3TZ0/z5NNPcDIf2Dy1gXW+tKPQY3ztxA1TJNZvpyE8s/gtwFCCF4KKouoJsbnERI8QY1hn/35kEFQk7s+KpcE4KfHNHj09w2CFMlxPRhTPwM/EkebRGreRyYFyPNAhTa5aoXR7/7EhrO9rkoGMUL1tjoJlimsde412+ZjE0U1T2FH07EbdxxjoTLwXVtsSQU67QsEKhadlyoX8DGcufYyvXf8VpB/Y7C6w0CULvUNKAzJyNYlSFXHDqqVm6vMBB5M+eH14O9x6ppoS2biotuI+YlPG4rXjnyHSE/1ywiv69MSkRWKhjcUtiESUQKn5PeGuhMIChILoQLh0cXp7Sp0psZJbqYeKfzuISEAKWiKhMwS3KabGbZnQRDjb6sTWnAmqaz2C9L4dzMq56xatXGIEOr6BX8U7IkjJVBMvD3Q1dCUWbuTB/hG7uzukTvnqV77B3/j//R7zg8KUHplusRoyt+/c5bd/7/dZDdkbxSuT7Q06SQzDKtp+IVibmZwzBwcH3Llzl8mkZ3d7m8uXL3H+7Bk2Njd49PHHyMOS5XKB6kA/FaTzMmmFKNxWd2PMTjQFZX9mdJSMWDTGbCi4NAFCqwwZbxgRV8HXQ8YpJkIWPxVEw0wUohNDMzAmEesh9uIGM4I0YYQLRZfe40iJAyhaOgNEFA6/D46yzBMobmAj4COV9A+5NyM9IqMrKgs/mIb8REnSV5dytNuIUpRSRnNdqx1wjhZqEmUdfyjIDqWjGzpO3krcuv4W537yDEkzcrLN5a2X6E5t8/LdX6N0e8RR90aOW5dN0xH+vr63x3WO3+76yNYlY6g5zoVZT4pypBShaB0lXEpLqLRBt9r+mhgXR8PEu+oIGTEuSIhvxiW+2cORsSZqpeCC5z8tprgijC6BJF0oajLX2gawyJGnsaMK2a1AiqZt0l4DFww7JLNQvCleCIK5s0OD+msJZBUb1lSDmmvk/1ZXtvhRN1qaQhKZ8fYbb/LkkxsMZZ8v/M6bXDr9BNeObrJ5fpucB47ncw6Pjjg6PiZJYjLbpOsNESqFIRfKMNB3E2SS2JjN0FKYTCbs7Oxw4cJ5zp87yxNPPMH3fOrT3L1zl+2tTb761ddYLFbcvH2TT/3gZXYvblLdAz+LrSKO0RQXHefeNEMWGdGBQIK3Ubw8J/qRUypSUhJaAx00Y6IuL37PooqWVX1OrEBEtey7ER0a0w7tWdavnrrJ6voE/aADUdgbyYJhfG2dtXUQCLlhqEqstkLRwcdtirW+qCpNCY76TolH3GioE9rch1Q1RT5KQ4CRPCYf/0BXttj7+hEnX7nP0WRg93CK5CmLVzP386tc+KGnSBRUp9W/aYZWWEeLjRdcb8vy/uu/1gm5qGm98fHBDSeYYiiOBKrTynjzr3Mv9atjbkoDbVTN5P9n+CZCzVJRxvoEWGFqVOiX+juVUK6Np6BaweCrpCEdW19Tiimgd7gAIMnD0l4GETJPcdwo4ggu+9s3d1Ain6vyZzZ9EZir8lPzWRxGO4zX3FRWLoXFyZLlcmBz4zSzfpsbV+6xf3iHvZsDn3j6WV791utsbe7w/Z/9DO9cu8rXv/Uy3XRG3/VW7JmUPIzPNlOGMlRlePr0KVTh/v09SinsbO8w5MIffOGPOLO7y+OXL5OHzHQy4fs/+1kmG4NFb7p5jZC2aGtrAgem62uxqc/DmLRVR762b5Q4vKtV4JeRq9Hbdi+ZVHNkPAroPbEj66cQaSrRYrmqn5Ec+qdVyblmLtlq1iTiSBfQKm9CsVB5TUq0f9cwIOZxVP2prlyrAymNTgjFFfVj1WSFoQ3U6Zh7ZDzX5nK85UKB0aiUltDYEGwSoV/OOHjjmMOv3mB+5y7nf+J5juZL9l8+Ynj7iKPLm2x2wCqQUX1Kfaf1RM7mDDS8/8HXhyql2WTHt1U2csv9ZpWIWrmPnNx39NQzETw02NCSNQbzl6pWKRbKEUKtml/zZip8Dh81MqLbggU/ZTxNcjeueEuHqHeq0RIsATSganuW++clkMoDE6yuff2txjlMdWeVkYtFKB9p1jO6U8bHY7CR16Lip67ETSNRLhOEMIJzBQOlJN555wabm6e5ee0Gb79xm7JaceHsaT729JPcun2PkjNd8uxyJ+l7EjsbG0wmHXt7hwwr20iWGQzL5cDJyRxVpeTC3t4hr77yBkeHx8y2NsiXL7Nz6hQvfeqTnL9wDlDeefMaz22fZeNUbPAQ+DFScqpWkvdrc14tXHfEkXbwL83KEmsYir7mupXqIqi7ZeIWsUQQQaWCgXAhwoUydDuW/MI4goiOZJAC4iUZdcMNo+9mCkt7bylIN+JQ/D4hcOFpCI1TKv6MSgW4sqtEerx/UAnekK/lRUW0sYwFuxm3MIIBIhiVfah1i5X5jMO3JyzemCP7Cy698BSXn3yJ69+4xvz1m/TDivNnP8msm5LoWcrKDeuDqItq/EMpj4nwb3d9qFLa2rhsg0ehDKgu3Qp4AWT4uRS6boIVlZpiMP87FJKFModiCV0iFio2uOv5OeJWMBSPgsrKDvkjYIwFdONol5pNq5aQqalfKwdIIwudAkoCjaeiQWMiYz24JM/dUIioRiiTllBap97zaho3EYKFoxxxhYW0o6dtDtuJrnZv4ypU3auNt6qFjVoV8ObWBGTgzt1r7N8e2Lu1z3tvvcf2xhZvvPEq3/up5/mt3/8jvvqtl3nnvXcsBJ06ihZmkwkHB/tcOH+Oy49e5OzZs7z93lWzxY4iVkP24AD0CAeHB1y/Ds+/8AlO5ie89sbrdKJsbm2yvb3N1uYWs6nlIRkf2KFrxKYCnXN81I2dxryNb5oUaEnHp9iYUk5+nprUo93FkXygdVNo4SZojkNMHaAkD4DoqLkdY1QanSnccFa0b/xXJC7a40vd5ep/F+8IYE3hhgaFE2veQcuBG6FkH0/8vnWtjJ8/GM00s2z63D7b8urWe1pFtLCgdJqYpR06pgzliCUrVAW9N+Pu1w/guCMf7nHhuad4/JOf5NYrVzm+fpOTozvsnNnhlTtf4OL+bcr0xDeVmn5A1/uux7OrO7eWzvqB14cT3V0ia1rT8CnNAKGjYyiDbVZR+m6G0PnBgBYO70n0/YwkHUUzM12ZAolOg0UpZQVkcl7Za3tSo7V6WHkkR9cW0E7uDQ7Co1iqfqQxZB0oDC4LkY1rUbzgc7KH1Otyu6AUQDooOVfeI6J/qevoHKpGuN82U/AFDXbVYmDiOamdlRdWA+joyDE208gjWB7JfuEeOEcV3TSLMpsJZ85t8Qe/+bs8euoJDveOOL0z5WSYc/r0KR577BF+8/f+CEnC1taMYZmZL5YcHh4wmUw4OZnz7LPPcHQ059bd+5yczMm+wUHo+inDasXxyZyNzSl0wt27d7h75zbHRyc8+sh5uq7nzJmzLBdzVsuOtBE5P6s21kC3KfCj84Ui1SVD47nBlSVXWIYAkm/qembZyOqKtNYlLWjxgEBLIJLkrXHKGuehvrlM0ThJvfb9Ahr0QITipf1uZEBql4RwBvxV13FCJAbHd4UoJ7Ht4T9XcQWro29ra7/jqKc1orMXl5QqFxY1gBZE6pnc7XnxzKfYffoFTlb7HO7f4etf+EPuvnGD4eCIlBfMusSpM09ycPMWJzdvsDi+h55ZUj4B2y+e4XhySHHUGxnkNb9JLQmXgATxmfBbP+T6iNYlU58HRbMjH6wOphTo+95O5RDMamnyM+CoL5O6iXE2ptVQsXav4glghppsouzo4YkhCDqEnq43obHDGO1wv05mQDIB1ww6UNQGoyXTqW3eVF2n1qI38jomDnW1jrVbE2btilvGgaLKDFv4lCYeIXp/bVNtp4ojDBfSnIfaArcppVZWUnSgtZwQz0Vy4kHtZGA7DsdD6snun1Iiacdjj1/i4uVTTHLP9sYO9+7eJ5fCrTt3eO6Zp/jGt15j72CPLhX6jR4RZRiid3XHa6+9Rdf15GFg0veuHIT5yZwoKp1tbrK5vUE/mXD37l12d3Z478p75NWcSxcvslqtuHLlLZ78xGctOU6sTUjrChvEtin0VIMiEZqXhqyCexNBpHe3wvpTVaJ2lDcnrkCb8vbeWY5Qui4IYcsTsx5cmYjyysiQRBUADMZMxHtEYXFNOKy4qykm7wUVv6oGK8DWmltep6WhIaW6ksEc6NqnA8WzphDb+Ye4IojoHzUhtXg7npQ7jt5bMX91yeTHt9HjzMGV+7z85a9w573r6HKfLi+YkLl48SmW+3c5OrzPsnR8/I//DIsLdznZuEsRoVMBR4MGKPuqc1IXhyEElyh0MvnOkdJ8eatmR1cf1geuxZBOoJesUedk9VkEfC8TRHojKv3Y7SRquR5SQA1tWbN6sY6RCtCRNDGsZabaELtkEFQTlnGbe1cGpXYISFAjNdFfKKygfdaPzZGOUoQ4UMA8TXsHKz+YIt5eV0O5lVw3hWpk5voiiAvfKB+pJHNxk5jrGbUp4UIULUS7YJvPrkLglt9iCK9ki7AsVytDrlPhVL/Fpz77Iq9/5SqXHrnIsFxx4/Z9fuu3/4BzF8+zWJywWC4YysDmbIOtrQ1yVo6OF+wfHdMve/q+4/HHHqPve65fu85ysSCOGQeYdB2pKKuTOXSJ4/kJM4/MXXzkItdv3OC9d99l795z7FzYQmQwFxSp7x8W3GTIerqbrXKFVXv5tKiluWvJ3ezIqM4Et1gPTECrsgpUNgIsGA9kyNUMwcqVR2wcf484SdYEpyJi+6y7aZ5JXd07/3CtPw7fr1geneCZ1zVvKpjuXN91HNKvGdaMlCGRZgEyUpJhcONUlTgNqNQxGPrqJdEPUw6vrDh+s+PcxiVefeUN9r/0Vfbu3WF1sgfDPt1mz4ZmTm/vkJeH7B8doTNBN6dsXZow70ExA15ETBERijdQo+85X5eIxMb4Pjx18iOU0sn8emsbWpFErouRS7E6LbHyjpQmGDJY+SkiPWk5ZdrPqCHSsRZVJZeluVueJNjlniQzh+JGYIdbZolrVk+DdN6qs7iFC3kYk2wdkjqDjUXtnZIacnMisxJ+6gKqhc4nNKui0k63cM8iEPXY3nl/Ir+NxMlx2twNzOpHmLyooQXjXjLJk0AbDW6QtzYlo0Cx8hgRRdLA8cmcYaXkXNjcusDn/+hvM1ttsVwuuXH7Hohw8/4eRQtDgcXJkmFQNlaFvp+wtblBJ1P6vrOG98De/Xs88sh5bt+6haoyDKYsl8sFXVImnTCbTZlOJ1w4e5bHLz/KcrHk7Tff4d7d+5RB6LspIj3aBYE61M1kfxqSmVSD425yN8oXE29xXCOWwff4plbn4VxxZFX6TnxNg2sxFGaF5WYEVQeb7xSuVsiZv4WMqw1MQKwsysnsIJw1oxUFhDHR0WfE3zO19auuS0S6hMjbq2Mk0FFLpymujcZ9pMLIVv60uq6tCLqAt6ZOsJpw+C4srm9wbjrj6M5V9m8XtLeocOoy233HxUcusv/eW+y/+x7DNJEf2eXc936MYSNzg29YbCFNkKg+oOUyrp1y7Tsm2h239CHho9TSRx4cUKFWWWEux8oH3XmnPytKTaUnpaES3cZPGyewWMVZWup1cNHiQXyDZlZlAC2mDqRDkvffxiMoniwoIixWPdJ1pLBIiHeCxCG/+IL3oz7dNkW1nQKRRzNBsNINdf6nIijMTU0CUqG5uVQ6mpsiwqDZlYwVcEbVf6t9s41muVnhCuCL68s6bshVIz3JejGF9U+dQ2Zhc7ZJKXY+3+H+Ce9duUs5vkkpytF8gWqhn04ZnKzORVkslgyrga7rmE4m7G6f4vTp05w9e4Yr12/Q94mjo30Wi4XxLi74Ja+Ylo6N2YxTO9vsbm9zanuH3a1tJl3H/OiIadcznW4w6TbNSESJUS39MWXfuRvWCHFbt9RNDMV4sqoRymYEW3sbUwOlFOJYbSh1A6tmsq5oGeUms8oK1RWqi8ptmMKL880CjfbVd4qDAepyhPIUqkIaR18N1bmhqz4bqHfblPqcUFCjUpnqJopzoVJlJklXFZZDyrpHa4AEJUsHOpinocK0KFt5hsx3uHJlxeqGML93m4P5AV1KpI0ZXSf0Wtje3GDz1Ca33voWi/0byBPnOf3Zj5PObZG2p8zUMqaMa2vpQdHIz/i62BExLy26aSkWpqSiw8e3uz48ebKqPK0um0h0ofEckSghECHXSIRDbC3QTcnOsZgArJBiNV/Sdcb/gC9QZigFugFy6GDbyCVHQpgtVuoiutbX7I2I2tSaKV/4WqqRGsnWpc7fU1wBuX8cXI10owkUqMIbKQgB69UJ054uTbykojV0qyn+InTSW99uvKl+WPpwQVyYIyKkrtTb8VYefULpU4d0wtHhIa+/9RZ/7d/7Lzg6PObMzinu3ttjma0Z1yIfM5n0hhLVDwMtBUkdq1Xm/v4+ewf7bF7fQCksFktP9LQ2MEhhMvHTaTpLLpr2Cc2Zvu84ffYM9+/f487NG+ye3mJnd9ff3yKXkoTivYNMUGw8qgn1RnhR2hJZ2Z2T+B090bpVu5rYZJsxeYQuXAeJ9RzodCCJJc1a4mwY1gFkVclwa6XhfcNTKIRI9RjIZaTAJBE8VC4r6nl7gQAkwvvQMvdDOTZkHRHdqA6wwtpQkJDoazsRj+cRxrz9JFy7zs7Py4boJ6Vje0icX22xo7tsHW+Q9+a8cnWPkxPLvEdgur1L0cxkY4PNzQ16CrraY7l9zJk//jx59jG63W2YJIpY0rBWAxpaN5JLpaK2mA8C0YonyWry8yxchtdSKP4elZIdBBhIIzT51CCtJEqyxLR2cqZ/NImVqCiMSwjM/VqtPSNHGj0W4eq83iusQt3QcQx1oA0VcEEqOXt/bgtld9I0dYuSNYLBEufswEt1niYmTcRQVybOixtZy+jqGAtjN3ZXLJPLslVDazFXsRSr7u+mrETQ7PySDzAMZUotIxmiPslduNS1DRm8glviNFnxa//Vr/H2m9c5c3aLWd8he5YBnlXRbAmNFUYXX58usTmdMl8smE43WCwXAAxDJnWuhJJFqURg1k/Y2pghXeJovqDb6tnd2WHa9+zfu8/W1gaPPXWZ6UY7MkkjiTU4G0wBO6ANP8XHE2e6QY3aVaPYeMDGqQSqTHVekgikHtXOghwKKt4vXgvZ3bWY9KgU6NRIdDum3oxuzktDbmUwNSCQPFUDWdH3LRqc0gQvorEaRyBaDEcBtmjITuB0NZShAyrufjmNEPxZlJ2Y8vJUgzJnJZmk0OXMJHdsLlacnW+zcXOPzc3nSVeOYOMUdz7/BW5uDry7I+R+Yri0V7Tr6PsJ09mErdmMp176OO/sfZH+wg6yucspPcXO9Bzbk7PMuhlzPeadvdc54aZ5Em7cI7Wj5o4lbaUlQcLH8qi1O+kExik5H3R9eI9u6dynNgGJM6EkcmSdgRc1JFEIOGkWgDXNTvu3a1pzBb0Hi6MArcqvbW7blJg3IwmNJvt0FRLWBnG0vI1wJWsfmNT5mIJ8baivaKpum0VAFOK0VHkwbBtxNXutWtkvShx5JBWaJ1NUefDsdpuX7FxYRF5y7cYQ4dPk3QoUcovaiN8vNuvx4oR33rvJD/zISzz51Hl+7Vd+1yJrEgreyIVcWvJmKcqwXLJz7ixbW5vMF0tT6LnQdT1DjvxpG+Rk2jPrJ4gWui6xvb3Dqe0d+r7jzTff5NaNm5w9c5o/8+f+POfOblKWe6RuykJPyBK1bYEUoKQJSSy9wmqJTYEn940qoetthCuXIvF3DwBkV2YpYYTrxH5XbBMHAVu84ZhIZGZbSjDOLfZdb2kJfohoVYiaXKEFbjGlaoiotUdR72SQJNE5vjek67WdgeiI97QriQVrLNDTGzJE6dKEPk1JasXZFIsEJwq5W7EsKzZLYudEOXWwQfqtryGTCYkt7l3/Kv21uxz1wu2XX+HqDz7H6swFEpllPobVEu0nbPTbnEpTzk17Njd7zp16no3ZBmeGbc6cfop+uo0OcHTtNrtnzpPPneLdwy9DWlLKykaSZkTmvCHKTJHWVlcQ45ldQRuO6JDvpMlbhDPDf7bokTcKr83F1K2q0cMt0xXCtxR3eeJ/VJUurSeb6+D9ckRq7oqkZJ9ztGRN/92F05rKWNEVeKRGTFFq6SgilpjpSrRm8EqqXEeIVtsNZSTso3EIrtCCe4oTSIxQj8S7lEzgcyl0fqSNCV4o5eyuX7ijDseTmFtD26CttMc2ryKt/kuhZIU0ZzIr7O3vsXNqh/MncPfOIatVQwfjqnxUWa0Gjo5POH1ql/liTh4KOWeyp350vfWf6nvj5YY8sFoJy5M5mxcnXL58gfPnTrFcDGzOpsxmO2xtbrE19Ozm8+yee4xXb/wBe2mPkobGD3v/bpE2n4jVeQl2BHSUhdRcITUJ7KRvxsrHn0jGj6Te+EGxdTNll8ie72ZEcKjFUEhOcncdlh7aI+rN/8gUXVb3TULZSKGUhd8rmul5y9gUzn1DvVq5oM5IZ9RbdQlFPbAi0ImylQtb91bMbtxncueEdG+fPJuw8bFnmL99nY3dTboXnmfYv83s9iFyoOx/6RtMdcLByXuc3Dvi5NY1unlheXKCyIougSRlWBxTliekLtEJbG9t89iTz9BPEhsbZ7i42uTOG7f46qtf5sUXV5x79hmO94545UtfZvfMBunT55n0pxztrOhST2KCepjf0nJWaMrmtmK8sdKRZGa5hW7Fv6Mmb9Ou882TfFGttUXOrR2FbVkTiiTWBEpYObJqGbKlDEgSendpwCGzh1m7SWvTkVIPSavLYTokrGREdGyxu9Q7T5JRL3hN0iGe61OKTVZSjxB6Tkd0fexSZA1bz+fUdSTpLRqmYm1C8Ra6jjSgWB5U6onEMJGOvpuhKMMwp+iKTgsReYBE8v5J0aEzdb1VeWNIPprfRcg7dd3o/uJE6rQqQ9WCbm7w4gvP8cjpR/nWy29DKjz3wmUm79zkyrv36LU3Pi55QnHBkKPC3Xv7HB6dsL21wWw6ZbFcUrTQJ4vGJTH3LYkYST5kdiWxMZmwvblBXsw51W9w6pGLvHnlKl///Jd55fo7/OQLz3H11f+Y83/xxzjoe3etnQ+TZIGOkeGC3tbOjVbvGd5ZrbtipHvkUTF3KBdFrBWKRupKb4eKqn2maK4n4kjk70gYAUe4OfiQ3g1Icp5QR5UHJuNW/xZGZUJKE0c/U1QhD3YMeUHQUYtZqzgwcyYrmGjPRHqmK2Vy54jJN26w/KO3Wb18A707J68KkgcyytEj55hdfopre7d48s/+GWY3biEdnBwec//Lr6BnNjh49wbpeMFQlpavN2SWWx1F5izn99G8suB9KegwMMwXbO2c5tTjl3n5j77EretXubt3j+XBPa6+8wpPP/0sy7LkZBv6x58Fjsxrwt1PD/OLWjpMAcT3kZV3WRF8l6bAFGFKVHeEbfz7Ukqnt56qzn9tbOXkFVBRRt9NzIVLnSucUR1OSpRshF9R6y0cYVeLwnS+8QvDsESkY9LP6v1TVG66z1J7CQV6kp6gA+05Zm27NDF5q1FD551cKEWsNUfrUtjXjOsuTYDOG7llii5Ao9m71/cli8x13RTVQHHmTua8IpdlrfS2hw6t7xHUNIouTYjWhFEca/o+MsCTd/gzS51SO7pGBHY3lJ/6sZ/lzt0bfPO1N/ne73+Jn/njP8Fv/MYf8B/9+/8lSSfIxDLUs1ofIdXgNYzAPTo6sX+5gS/e0rXvrV2riNB3iY3OkOutW7fY2Zzw9OXLnJpN2drY4p0r17j21hu8UPa58/oBs51det1he+O0GQ0xh6rrZnS1KyF1flQsabJL1qI4So6Krii6RHXpVEI/IiqKKZpEnXsLmERSqjYKQDonxr3iQIO3Ewory1uic3dDKXhhbRLnDBMiU1dc7Yw+46KCvC8IJsvmwnSkJPRJ6HJhY9UxGWDrMNPdOmF19TZHf/Qy+evvIveXTLR342EdHNO0hzIgt+9yfOsuy9WKxeuvMcxX3Lt6jdW9Q05u30avDdbYT5TVcgmTxJeOf5zfv/8zPP/GH3J+5zqTJAyrBcMwIF3H/eWKr3/h93j0zgtcuXqV4+N95stjynai39ni8MKUC88/z6VT2zARSlmR3VjaFkp0aUaqCZFThsFKmER7l/EI/kQipfFv39G5b5PJaSpzkoL9Dy+nEb2Wo9Qjkhjyii7S373xU0lD/fyQ55W/7LoJSueFogNdWvogrJRFnBQruVQi2LKQ7ZUkWY8hIprStbYNKc0QeroymGWbZE/abNm4pSv0XU/LnbGN0ndTsmb36SHnqSsEn66gHIr5yIjQTaa1d42kAckzc9OcpLWozaiBlivczluDigh9cqsshXaGGI4a3boH3xGuaCl8z6c/x/7RfV594z0unjvPssx599p7bEw7hlIYBifeVelTc2HrKbRinJN1OojWtBYh7MQypaSD2caE6aR3xFI4vb3FhfNnefvqDba6nsuiPLnVMbz5Cud+9ufZPHOBSb9i0AWSCsLMRMkRTXBDrZdR8bFB16nxXMXTUMSSHpO7aLV5WvTXFm8jPCaUi7fASZ2dg1L8lOc0PmxBazJv6npz+13OTCGuPDl2hp3TF2VGQooIaaBhLaS+WF3ZsrC5XLK9X5gdF9LdQ7h6j/m1uxzv7XPj7ffI124zG1aAksUijEYkJLLTBIhQOp+HiXDllZeZ3zlgODykz5m8XPgpuBZlHvKC68Oj/Nt3/1Xulsu8/MUf4Z/+9L9O7o5sw/c217nMuX3vOgfzA07yEt3p+dgPf5qdSxfY3D6N9FNHPM6Ppp4+ghTOlXZdX+U0xZ4blUTVMxjdHQ7DupZv9feqlPo+Ws2aFlCwY7trHx9fHOmNRK6wzqC6vZOQNJGzCVEnTkBiZSwiyRrdF9t2fTc1pTQKkyqF1Pk5a87FmIpLTl4nK+XwYkdRI9i6lBg8nqnatRE7yuiIrG+hNsrBfPBEqrWWOM8jQbjjLVQl8jDs1p3zFqJxkIF6GoX4I5qFUDysT++oz/ZjRpEgbINctx1kc2Z0WnWnASb9jDOnz/HJF54n58zewSGXH32EPn2Dra0ph0dzjpcDYQ2kM3c8JXXEiHOFASRtc+c8sDmbsLO1AaJMpxN2z2xx+tQujz/6KNNJR14tePvKe5zsHTPb7UmL+5T9OdfefJPTf/KP0zGQ1WmABEmmNn+pHthu8+8Gw97PuR8VF2aP8Aqgcfx68IsRBWuHDoQlLsFbiedsd4LIYEZDTOlY1As0GcFsbIKnn5Qo5O4ckSdH1GHIbD1mKvQDbM6F7f3C5M4B6cY+3DuC+QqyIoNSusLi6i3uvfY2HB0yS9bHPpEYiqXQROkRWC5c8e4ccazR/JXX3LBm6+yQEvvDilvzYw7zitsnhwxyguge8Cg702O2NjpKNyWXJTIsbC5KoZzsce/kBttPP8enfvYfodveovjxYdUrcGMhXkjdcoxiX3kgS72wWbpqQO0/r2xQqO1equv+bfTOh/0ylwOCym6nlIp3RfSWrpIodE4Qeu6FRueAcD2MVC46uCb17IuyMLRTCqorQxOjrnxRrlJPjkha+22rS7mRZh3JIXOdzLIgu0JQLxAG9Qp8bz0hqXaelOInupZSyUnTCZYFLICWzvmRqr8Cy1ByqgmWtghLPFxo5SlIbU1q37MjZ5JnF9ejhDBSVQSKN+zCo3JmGMQRQHBVmOYscy4/doZf/dW/y+Joxdnd07z0yWe5+sYNTo7nSAdd35GLKfhagiPZTjYWq2VUdQgOzLrE2Z1tnnv6cSZ9x8n8hMkkMUFIfW89zjvha1/7GufPX+JEL7PcuMArn1L+7395xZlHf5F/6daLXB42jPzMAt2Ghb6zdwL1yKXpS3MtS81H6i3EXwbPyi4kmaLqPJU56JUqKJ5z1spAxhFZC4KYTbXSps4zzi1AY3yJpInfrjDxVAJI9CnRk+hyoVst2FhkNg4GJgcD3f4SOViitw4Zbu+xd/0Wi7t7LI+P7TRiEbQTJt2E/fduUOYn9LOpbf7O+B8kUKMluZqFGADLiSqeI7VaDRzlFUfLFVeOD5hrYV4ypydTLk43ePTsWXYSfLz8c7w2/DTPXvgDNlY7HK0yujiklBVDlxgQ5Mx5nvzM9/P0p78X3Zyhmuk9/6GgFr5HkDQxLkoUOqdAPALd6gpBSjLUGR4NkULRGtVFB86/b6W0WO7TMlBTtUZ4YWvOg7ltSUjFFrO479+ljqLthWtmcDEeICyyuMtj0bHOquaHBeOK5xLpkUUqVxBaXHIQb7gyMstj/JVFsXLJa5a41uok4xkYTJjDDSTHpHnP74rQupqAGWSfzzQRtDcSXZ2DMt6iZCd5U0uqDFcsjkEIi5REKGLJgyXbUcjG93gtXKmPQcG7KVjb34vnT7O5lXjiiad57JFHOD65x7tv3yCvTPF0U9CckC7R92JBQD8bTpKF/nMuDMMApbCzucXprW02JhNm04lFQkWZzqZsbG2CJHZ3T/GnfvwnIfV87JMv8vSnnuL/+6lX+cqjXwWu8v2bE37h3mOkJEyzoJzQZWEQIcsA7sKGErYjo1JFI4ke1cJQ5mZ4pDfu0q2yFusPHSH+xAStwQu8S+oSpCO5kbKyDZODaPqWRECPAZhqzywnNoaE3D2hu3YPbt0l39inP1Am0022LjxCmm6zPFpw79otDq5c4/jmLThZosslachQBpIkMwRi+XRalNR3rIalBxfNtS9qqGgo2SsZzBiWsuJgNefe4oT91ZLbizlg0euzXc8j003Obm7SdwkZMienphw+cY7drQXfc/s/gQs73NmfU85so7szZPMcGxfOceHZp7j4zHP0sw2LMg4nda8GXRNtg6IESj3TvrV3yaTiwRnMQ8D7hpkdtU6p1mUjkli/Q6RU4uwon6CIAoEhazsNNqOanBhUSl6agDnkw333gHAauNevYRhInSsVTxaz58WmHyEC1Spsln0d9zLEo6bhLGoTjdeRuuFLbTsKkQllTewjd6m5ltZ6IawsDolK/b51FXRXcnSq7jhVIdJ4KwpgqGNJ0tN0mnrGuiWT5rqAZTRVEW0yN9IsVygkU9o7Ozt8/+deYrlacPb0Bj/7j/4ML3/tXfZu7zPd6ElbwnJeqitbUZiash9WS7rUM+knaBmYTCdMNza4cfsuZVCWqxUXLp7l1OkJ9/f22Th3lqOjE376p36S6cmS1a2rLN96g2ffucLZP1PY2drhT947z6UDYffWgBwWhrdvM/25H+Za9x5JYSdvMQwHHJ+aURhYqVhf7rIiFyWnVa2vjHUiRyqHYyCPulpVwTHRcDAXrTGS3jtJqLfNieT+pAU6oS+JzVViZ69w6tqS4RtXOfmDV8nvXqecLJleeJSdJx9Dz59mfrzi+hff5PD6NVa3bzMcnpBWA32fICWSeBmSinFDEhlxGS1u8wQ7vcS5IPN0CsuSWebMncURd5YnHA8rFnlgu+/Y7ns+eWqLSbKMLFQ4HgZun+wzbM6Y/sjHeOyf+Vk2X3gO7YTVyZzZbMqF1dK4z643lOw1giUds1gdVw86+i2JJMqQbb/UX0rlQptOiNYvIfOe+xfcoPcPk7Gb9xEKCT4yeTJCq8YTBbyOyvFQGuHLC9Q8oYButbtksEA1tG+XhdWDywh/lIaSSiNCzZ2NXttR72QtRC3Sxci1G21iJ1VFou2oCW28eyWRwfE0I9dIvCRA21i8lAYN7izYEbcZMuq7VL9n723KV963Nq0bgNlv8RxhIkwdm9DTK/Aljt47JhyZFz/2CRaLuZ3fNpnyP/tn/0f8W/f+Q+4eH5C2Eof3liwXypDFXcJWqY5mhjwwm25w4dJFdLFkvpzX7PwLF87y2NOXOHXmNP1syhzl6t17PP7kM6TVgnz9Bl/9O19i/jt/xP/n3v+GF77/h3hSty2C9c5VdDLh5Le/yuaPbPO4bNCfTFgdzZC3rnPuYzuUyxcpesj9rSV7vR2EOs2J6aqj1944wLDaopTB8mKWSRiSshJhhRPSqSBlgC5x/gh2OMVJWlI6C3h0y0zPNikr3WLJxp1M/8Z95J17rN69yfHXXkOlsPXoo3SXLjJfZu7euMHJy9/g5Og+eTFnMgxQlkzE0wUKMDjJHj3etTMlJYrWnCdDuMU9hL3VgoNhxZ3FnL3VkqyFjZQ4N51ycXODs5OONLGAQy4DkpWchOPTU6Y/+TlO//hnmFw6z9Yzl9FJYnAZ6yabZBH6jb5GzIfYJwqpBBHtymbs/oZEK0CcumMyj3gKhrbcN/WUC61teOxn0ZYoiI5AWh92fXiPbidmW/1fcTfCX0TjVa2avRIsYgRyhMAtEbL4BmgN2swF81AwAambEmuhQ1eGjrwCRVn0o5VqqGiMuk6ydS7wiZUecVcURzUGO21zFqIgwt5B8MiMa9zIMNaA/dU3juN4PONaQdOouHYN9YT750IbrqdQeQNxi2rzZGSmaO8WtZ12EdXyDsQQVSaTjr7bdDdy4IknL/Dkc48wXB1YaeZkOtAN2TLIi6NZT/oztJY4Wc3Zv3+fszvbLI+P6foeXa2YXTrN9qldlsOKnDOr4xNkY4crr7zMEyTuvPEar//2H/FTf/mv8INP/yDp6oA+OiGVKYqy95//Mt0rV9BXrzLZ2WR16x7XfumXYNZzWX6cydUEJydc+sR5zm0Ksix0ZUY3zEibW+hsG+mn5L5DhgF59W0rmziziVw6w3J7yurMoxzmY072XmXeHzHJidNff4dTl5/iXJcot27B3n04XFL6FSe/8zUOrt9msVBmZWD3R7+Pkjqm58+Qzp7m5P4eR1/6GsNqwWqYo2WJDiuSDgxqwRUjjgeTrWJZ4R1Su5FqLFKxdh8necXN5Ql7qyX3lwtyUaZd4txkyid3T7GRhI3OzGvx75ZcKGKGa7E7ofuZT/HoX/xHmD39JKU3+cvJ8/qcA7XNEmrHFIWxr54ywaizAZHyk6u8t74vLmDhlvnvdbxPtXi2u8mvpfkGgsKMfcjsd8Ip4XtcUmRYM8pydr8yqu5r+M+/6v4l4ebhmzt5iBzLZpXk5K2qbzar7i4aaQA2udWfLaZ8DJaPolkyei5mKSrqKtpKTMQKJW0Rkk+wO2nqxxQEMtOoIm8uWIwxSWrzYnpw9OuRdq4lKo3r8tmrhKzWSObgClLbHNcxZSPKC9U/F+nW6hOjR5B04SpnpmcmzP+Fa/TnbqJ/9TTd34wyDj+QShUdFJ32SFKmUthOE3YnUI6PSZOey2cnXLpwHtKKL/3m32V6+jQbu9s8+shFNidwb68wvXvEK7/+O7x45hI/+CM/QXfhEcqbb6F7R+RLmwxHRxy9/DqnTgT9yivoi8/y8l//mxz83heR1TF9Ljz+Z3+e4f4K/s2/xeQnv5f06EUbe16gk4yc7Slp4cmcmbR/YrWEJwXkHBufe4mNs1tsDQMnty1Te8nAbPs03BuQazfRV18l3T1geeEMh9euM714mY39gfl7r5NO71CefZJ09T32dcXirbfIJ8foYDlmuSzIZUDzCtHcKgw8XcFI1ahoMOM1lMJBXnFUMldPjjnOmXkZ2O17dicTXtjZ5VTXGx72DNcixblCC+xk50ZPJkr/w89z4Rd+lu6Tz6JdzyDULhM4ggyBFXAKwwBA9FiKaHDbq9FCRjDg4P31tcl7batbxVsdtNi+DWapFkgr9d+WDDwlUgK+I6QUXexqvY/4aQtFTOF4unyq9UimKc3PV1qLUKobWMrgfrd4dMlDve6itHPAqN+N/W0kgHM4Hn0JikqcvGkTGfH80rgw9wHjO9FWpPJcoZzwKJmTdJbq0pFwvkPbggPtyJw6b1LHUkZKu3jeTJ0jgj+LworO5SmIqFhocbLQW7AmrVGMlMwtVQqSRqcNK4gWbp69wt4nr5FkYPsv3Gfnt86wN2Turwb2l0aiF4TJsrCTCp99bJfdXshDYWN3kwvnznBqZ5szF89xcLLgjXff5ebd2+zowCMXz7PKAyfLY17/jb/L7LHLPPnsZ5h/43U2n3vS3umN99DNGXu3b7P33lV2zl9Gh8z1l7/Ju5//Aqe0Y9DE7StXePLiWcq1u5QvfRk+dhHZ6EmbM8pqsPyNoyPSxPpWUQqcnCDLpYX6Fyfk3U06EbpuxsYLH0MLHF25Tto4i15/m/z6q8jbb7FMieWtO+i7t7nFm0x3NihTZbYzQ2/f4eT6XU7u7lEWx5RskeGcl5a3VCJC67lOmFuVnN3NKEfDitvLBfvDihvLuW00ER6dbfDk5ia7fc8sCdFD2yhBz7UrBTpHR0VZlszQK3zPk5z683+MnT/2PZTpFCURR0hZYrB1fRQSpbalbfsuEkgbbxp7RavMNLomfhw1eyMaRGOvQatuiK60GtJaKQrFWAKJRn4fTSl9lFLqsTOpol+yKwSccNSoCYrwso/G826MsQ9UoG2zlmytKAhXqz2zePaypEaqFVc0SSIKaPE70dC8TqzFRJYognQGqfb1wacseSuIBk+FzkP6LTwfiwXe00lHRH+cMR/Pj7uVYkWWGr2C3F30+0a4fRz10TpngZC8Yn4Ec8NdVCcSW8cEf6ZbU1Wof9HCI4vzXFxc4nq5xjO/Jjx1dYl+/AL7s56X37nFK3dPOMzK9iJzvsucRnhka0LqYff0DhuzGYucuXbtJoeLFfOszFeFbU3koSCLzNFv/D7bQ+Z7/pV/mVs3j3imCBuHh8gTT8LsDiwHljduMp/POd6E088/xRv/1r/FbJmZlxMoAye3brI4OqJ74gLLi+eZTKfo3buUi2ctbUQFPT40oVeBvkMfv4C8exUtK/a/9ho7n/kU+dwuaXuLJD3zMjA9Hkj7e5S790i3bjG/ew+eeJRhmDN54TLTt66y2ttDRbh35zZHv/7bLO7cJ69WlGytT9RboES/eBFlOz/OueNPsT/7FnvdO9x2d+zWcs5xzpzqe7ZTz/funmG765mJt2TxvWCNW8M0+YYW0JIpWVmRWfWQX3yUU3/xxzj1k9/HcnPGCquzNFkOhJMsHy45aJCRh6HFPZLgJYtvuwYYWqdLT2FxYxiun3khppzjkA7B+F+rbROyLom001pXKJFmAZbrZx7IqELtA6+PPPdNnVwOSw/GD9nPvZBRouvdKLEKV1geEbMapdiELtASfjcGN0f/qWeDxyG9EcpN4nlKJTkxbptX1LKSU0oVuaTOQ+toNJUkSgNysU0biiXGG+6Y+N8DJWrxbgljcq9amhFi8t8lR5YFWDuqWMKa2FWyox+R+mfMB0F+j7i2yOK2zWmEvdDTiR213YlamYYWNCV2Di7w2V/5E/z67/wdPjl5gfLEayy+co0zl07z9GzCyanMa3uZeaccdBO+fu+Q68uOiQqzOwvQW5y/eI6zF84wp2dvPjBIYjqbcUU+xcHL1/jcrft83//hX2SZBl4f5lzYPcWnlyvkeIlcuQUvbbKcz6Hv6b/vBY4TLN96j76De6s5uzJjuHPAwRe+xOkf/kHKyaElLZ6cwJVjNCXk/HlzwzsX7vkCzp2Fvufg5VfZOzxi5+/soKXjztYGdw5POJpt8EQ3hffegHfe5eT2XU72j1heucXR29fYuPAI3XSGHszRYUU+mXO4f0Dk5cVptblkcikcrJbkktmQTV7a+/NsD4+zcfQpfq3711jKIZemGzy3tcv5yYypWEtlDdBLIFitSsOMX4suW3uVwklS9BOPsv0XfpJTP/lZVtsTTorSM+JiiYa4ZvSM/ViXzealRc6ft+FxMU31YIFIlWjtWNTdUavuH6e0hPHUpnwQyx9j6W5j5A+aUTbFGNG7D+eT4L9Gl4BACikla3MrQs7qm8E7Isoo2TA2eBBhGoSt1sXp0oTVaomI+sS0Nh/tVNUIN0bWtb9PSdWXV4evVifm5RNALeLC6+ZGbp46gkvdhDJYFMvC7LHgkPPg0DxaflK5n+YihhJWxqUSFl0MvWLZ7HbSg81LzmbdrHtASKw1QbPxjSxY55hKtZbHSLEUi3ZoYSHOhu8sZZpJVrqDzPG3rjPcyPyxa2d58yub/MH2e3zue59l85lLHP/ea5x78x4vntvm1mbP7U65lybcXw3Mhw3OTpSL2zuc2dkmzaZ84+o9Xrlyh3vLJae6Ce9OfoK3zv6fSKcyP/XPfI1P/lDmq1/4fYaivLkaeHax4NTl8+jNW5TDY+avXWNje5vTP/D9XP/iVyjLDFMsf6mbIosF9994g7NPfJyNlZDv3gKUvDjm5N4+0+97iY2DOZIzGWF5dMjk+efQ67e59sWvsnXmFHu//3m6x85z61d/lzffeY9BEo/+7E+w3J5y+2tfh4MjhvmK5c09+tmEwxvX7cAECvNh6Ym5yu3FIYtiRPa14z0/bAKW2XieGVu8pJltYCN1/ODpi6TJrm/U0YaWhvSF5tabMbS/57JEEwyqLCdK+cRjnPrzP8H2T3yGYXuLoSqiFYOjlFQK1hPee9MXbVSLd9cId9A4SU8mrbClufhIomgmDnlQHDi4IQ5eNoI0lT8FahuWSHYOf43kCcPBZ8nIs2AUAPrg68PzlIr65IWS8IF75b69RCYq+UNJmCYNf9nciuTaV7xhWSQSVqQ0Grj9vSkUX1kjl+kqahmXZ1jLCmoafCGUkWWmmkJJbfL8Ulc8YcVEIHUtwa6lJEgbr4TrGj539CpSSBNTyGXw+SgoA+q9eoj0gOqztpSDUqwXTSg473FhCZzq5L67baVAYspUBF0NLKTQd4np/pJH97e4/esvc+0//q945FOfJpUVlw9XfPHOHu/ev8+T506hl0+xmCQevXnAT+XMt07v8vZ0wuH5R7l+/y53jwbeOdpnsztkc5VJJwsemy/5bM5cXhU+//gObzCh9BMWF57mzNY75GTNPO4L3Lh/l9OXHkFnU/R4AXdus/P4JboLF7j5B3+NTem5udjn/O4ZJktFc2Z+d49VP5AnifnXv8Xk8Ue5/ebbHB4dc/HUOU6OD5G7eyy0MD865Ox0yv7Lb1Bu3mJJ5s7eAfLGO6yOjjnYv83mZMrirXe5N+tZ3LlDGpT7JyccLlewFO6tjrm/PEEE7i6OGTzgsJF6OrF1eXxjlziJ5txkwzoYSOHG8F8wLD7N3uzrdNOleQIadXfJgzHZlUS4QuZiZTtX3s5BpLDoO1YvPsHOn/sxTv3497DambBSL0FRoYi3vSkZ6dzrUEuHwaO0UURtOs8RdU0zsbpLC063qHAZeTdlhGDUZV+Sc0OF6v4FwrJUHC/tYXy2HyOPBzuUgxblM53yHUTfcmzIFA3AzF0IHkRH0Sm87CTOmTKtmqoy0kBMahnWljJgxHdteq52qKUWiwIE2acGb6zhV0f9rIRy0Z7mSYWizDYhmix1QC3ZMNy7UJqq5hLgeSQljq2O3kcEgW/oq51ESlUY0X6laCbr4CgoYLSdE2a5RdauRIuV0yTBXUkn96UtniFPr3vyRNCCk90qbKlw9u379L/1NlufeIby8XOc3L3Lrb/6y6ye/AyXXniR15d/h1d+8Vd5ZVb4si7pNuHWwQnv3Dn0QxESpy9u81JRvvfmAfIL/xR/91/9V+i++U1+8J/5Szx69z6PrTIDyrQo7057DrqOl09t8bFX/x2+f+cSW598gj/zyBbClPt373C8TEx2znBt74DnFwvS7iYHn/8as/05F37w+1jeuEN36z5DX+jZpLcuN3TTCSdvvEEWJe9O2XvzLXYvP8LRrTsslwvuvf4a02mP3ryDkNG84vbnP093MEcXJ1z71sts7ZwmaUI2evYWB9w+yZRvfombR/vMV0tHwS1c/ejmDludZfJ/7uwlUzgKm/1kjdNsCMflOHXM0w2uzW5SE1AJGWjrFUfJgyP05HxiWbHUzGJ3hv7gC2z96R/h3OdeQDanLDA5Sl7vlr33Vol2uMWCE9ZDqnPDZXl6Ecpv6sEMojGSg+cW2b5sxI7W/VSpCOl8f0YQJoY3NuYtKoc3p3PNGyih7RtVL+0ZfOa/g35KzVXxly+Yskmp+qjht9niZN+E48LIeDnby3EgXgDD2mir6BoBZrolNz2jePO34ghLK/dkxbE94VLlbAsRiYWKVO6vHW7ZQvFZrTYnCDmKHY6pFAi3UKMHtI9VTEhMaWa/v7aiUn8b+2yUMUTUzBYzB5KyrDtX8D5YCSSmTrIGRC5Wn3TjiM0vLRh++Vss/tofkl54gq0f+17O73wcvnWVyac+w5kLj3D31l1uzQ/5kgzsoMzoWQCrIYMMCB3Hj5zm9y+e5ZVf+CcYLj+GnjvP2U9/htVv/ga/uznlZp9YAUMSpOt4Kg984t4VNq/96/ylX/jnePrij8Kw4Ku/93tsPfsDqA7cGQbme/tsnj7F/CtfZ+fRi2x//yfZe+tNzm5s8frttzlz9gJlf8HG1gzJmeW9Oxx+41tMXnoEOXidw1feMARQMkdvvYWc3kZWKw6GE/YWc3TvNnePT7i3mLMaBoa9myzd/U1F2ZpOuXe4x1Ob22xsnyIB09WKrY0NjJPxInJMVoM7UR2Ig5kZUROKucgdAnHqMeYRGf8YdILJeA5ORxQp9k7HXWbx+A6Tf+R72f0TnyM9fpEy6VmlznP1cq3FC1Lc6BOT4zgooQZNvLtFSuppBBEMie+2vyuN67RN5kho7JFIDDs4oMYDtT1afC9b+ZOndfq+bR7K2mb2J5i+mn6o2vmI6Ju9cPYanpjwIJLdJSUPC/+GWXxhFA6M78QxSUSJRRzxbbNg7lqq7lLqkmcde+GvI5qIrMX7RY+mVIKoKxXOpmSTWupJKNaGNmfrVqDFTvVAsS4G3oai+uM6QDRlc6sXvZ/Q5gRmHSDnqmRLNhgv7pvbBy0LttQSCVdbpdSeUU0IzQ6V6tJZFq92wnQAffse8//kD7j5lTucOvsIs/OXKXsnHP0//lPy1ozD0zPe/Y/+Ontvvc2QF8zJ7JOZr5TdrMw2lelswrJkZlo4P8B8WMAv/md0zz/P+W++zONf+CO+0Xe8OemgnsVX2Bgy33twwurMJv/4X/iT/PBnX6JTOFkpb711k48/JSyGBfeycu/+HpMkdO/e4NSLH6cUYfbOTRYpcyMvONd1LHVgmhNJlWVecvCFv8nH/8e3OPvMfT7/n93irbuGEg5WC45ujTLZXXFfmMzYEjhGeXq6yyNb2xycHHNlccBTO2d4fOc0RDhcMsc50zuiQFcEWRvkbvUAwBG6WF8tnLPLA8NyybSDyXTKis5dfZPvDisozq5cyJksytDB/NmzbP6pz3Hmp7+P5SNbZKwZXMLQlZs538P2jkEttA3uXIjEviq1o2MUnhey57JR96KNx+Tf+kIFr+PpwjUdxm5WSq5cr6qSXW5LMXoDxMp7NM4oDM8g9jz+mcYlR/JzffS3uT5cKY0eEha/1b94zpGMzsSy13JXKTRvhOBtouwYnThySYiKmDERHP18ULwLZDK/uuSKkAA8gOaWynOOiprS84mzbo5xOKbUxNWWY1TsTHjtqkAWbwwX7TLMKnjTL3J1oVp6gKXXd9FIPbivSBWo5GBTpvFs1QG6vnFdYoJUtJC10KsV285Kgt99nft//fe49+XX2D0qDLnnJL2Nbmxw7olnOfMXf467//7f4K33bnG1rDi3cRpdDcxyZiqZo8mUhRY+Lh2nJj235oXdJWweD2hf2Pzr/wkbf/e32Fksub454wf3D3h6seIr2zPmAgspfHKReabv+ew/+2f53h/6NIujA/qNTVZFOfb6veWgTPspV+/dZ+vrr8LmBvLc4+jhgtW9fV67e5VeO7oho51wb3lCSR33VydsbLxKl1bILpz/+BFf+4blJe2I8OLZS6DKhgibpZgToMqVo332U8f52ZRuGOiTdbve7jskr3zTWs5ZJP3HvrDN6OUfjnQC8SjZi8AtqXfS9dZiJA1MpGMmIGXJfFia4u79ZJ1im3g+hfzkafrve47pj7/E2c88Q96aMS+RA2e5fhpnGBLuosmUeOjOzJdjOkfQY6No6Doay9l+tZQBI8C18rlW9hIdN8bdY5uQurGsiMe8kmhVVFTdIy12kor0FN+jARJaDV10GxCbd6Il8YdfH5ESEJvJCW4wy97SICjFTxp1KCfSV9/WDmj0gUpE1qKRuG3CaEER6QbjLO4knTdWi3B8FPwFUe6fc/+XSlR3qEbpR6TAU921qOMzty/8frt/qSf3UiMZY6UZi1MjffjRyG5drU9Qq60jkONIIYVCjGOo7b6+W6Aqs6SWzbu5AH79G1z7N36VrbzDxx//DIfXbtJJYnd7h+PDPQ7ee5etu88zPPUIk6/eoiwX3ElHyLTj/InyaFbelMLQCYuu58/91GeYlBPy/gmHN/fYXxVupoHl1XeZbW+xeuY8s+cv8clvvcGT1w9YPfokV+VPc+Hgd7j4qbtspwOuf/MrXHzmOTa2t5mvrJ5uMp0iaUJW+Morr7PzO1/iqZc+ybVf+kVOff8Pc+PNN1geLthOM24d7HFQVtxbzelSx1SE1evbnFw5IU2hvHKOT20msiolL9gVZTbpIGdKtryhosLxsECkY1jMmU4mTDTT5xV5tUI78VbIZpBSXjGh94hToG2nGXyZBj+WKbL9k1hlf0qFfhjoeos8z1cLBs3oNKHbm5TphOU0cXJpl+2f/iwbLz1O98R5dHPCQGHuaLMepCDt4EjbxGHIzMBmP6o+pQ6K11jqmDQak8ZNodie6J02caPuh8ha54uhRrBdKk3pRSfOqK30oIw1bWwdXA0YBFIbLOiEmg4YJUED1g9/cGe5myAjVPXtrg9PCYh6LRWQ3h5ePFPafTdBaggROrp+VpP5RKzXdgk/3Vl9a/TmfZMS1b2yzVkc3SRSH8W3AasZTXwLs1qTflMu4TJFeDdH+w9xhdK5FRJ//xoiNbdMCHRjrl/LUg2ffJR1nSJzW4njmqjnzeHuo4d0Jdq/4mgqBCe7QhbIoyQ3URId23nK7V/+A6a/cZVTj32cO6+8xsXhPPPjzMbMFN8wVxaqLH/1t+kQ0mTG6cWCK0cHdJsbPNpNeK6seFMHVDveuzvna29d5yc+doFlt0eanPCzTz/ND0liMS9c2D1ltV3Hx5TPPUP37n1+6yv/Mq+Xv8J2f53PXf5nObjyDof7d5jtbnPpyY9x7a132T5zkdnWNtLB4cmc+6++yc89/SQH8zt86/VvUt55j6PlkivDMUtRNnPP6ckG54bMo9unOZV6dg873v1rp2Cj42BvsLSN3vLN5vMF3cYMhhWSM7rKZBfHWZcow4LZpGNjkrjbdRwcH3K636XvrCFe8gr+SZXJQhmcV/RDFs07UrKXW2RVdNKjsynL3Rnp3C7z09vo7g56bpv+kV3k0TN0l88hO1vI1oyNjRl50lE0M2ghJyOYk7vjZhAtnJ/EG/AzTjTGS7O8XKikGsWOyFh4IFWlpBYxriUhSUCtEWLShDraj4j1WJlFICqOuipOsKfUEX3tS1lWRdaK59t72K208a7g9r6rraZbadrfr1LSYoNyaBZ5OGA5GHa0UPINaJscX+w0RgSey9RhkY5SBu+Z7H2NR+Rv5B8JtMZyIx5OHZZq0fr9nKMWLnJ9XHuXwZXfqmaF16TMikq0TqSMVqvBVy/hcJfM0KDWYktTzFiGerFSkZiPcCnjan68mMJ2NJfEBUr6isTODVucPpwwuw/H1za59dZtLpTE9/7ET5EOjzl+7yYF6NMEmSQW8yW6ErY2t5hub7O1XLK9KlyZH3FqtsMLkwlfXc15TyYcy8Df/toVPn5qg0emHaow7N3h1LnzlM3E0f2bnJzM2Tx9msmpLSYvnWJ+9dPoTWGhZ7ixv8XWbuHJZz/GmUuPsmLgb/3Nv8Pk/AUGKciQuXX7Nqu33+Cd557m7W98lavDim054oJM+JEnPo6uCrLK9BsTXr75NveOjijdhN3Tp1ieDHTa0SVhKCt0EE6WJyyWMOsTUga6nMmrgWk340w/RYtxRZIHZv2Ms11PHgrDfIFudEhv3TxztoMkxNptkpOiqaCpZ7nVMVzYply6QPfko+jFU8zOnkUunqK/sEs6s0WZdnSzifVpEiVTyL5HkuIN6goR/FEUiTQV58GCbDaD2JsseFlUbGgL8o5LP7SS7cmVhxm3SNOxvWo1mdEbDHMPNZw/oVRtFI5e7NEJEckT9xpUikeIDSSYpxNRwPB+HF46zGz5hlA7uYp5Dup/b33NPvj6SKK7nQ8+LiVJngIw3mTRgL9tviAjI8fGoKNv/pj8Okdan5lSopOOIXvSoUjTvklNsTmPY5nX4RYtCX+4FDXCj4Ho9SRiiiPyLIr0PsaIeASEDjiTie6PSaaV0IuoYg1tOvlmrmbnkRIPsbr1MPdSRovoLXbVzgdLKkznhVPM6G7cZfKFtzhz4Tk4dYYXf+AH2f/9b7D/3g3y57/As9/zWS5/7tMcX7nOpJvSI5ShsGRF3y3pOmHn1DY7x5nJ8Yo7qzkXtjb5bF5xe1ix7JT3ToT//Itv8gs//CSTrQ3mJyf0Q/bmah27p86ydXqXycYGt2/e40L63zOZ/vN87PveZevCK+yp8NzOGe7fuMHhEn7t177Ap37sTzB8+UuUl19l683X6Y9PuDmBx/sdnjn9GI+eOkN//4RuEPrLjzL9sz/D4bXrfOuv/gec5BV9KSyyLXFfLL8s64pcYEDpJx4hHZSytFSSG+WE42HBmdQzmRhxnkrHue1Ni5JJARlICbo+kcvAcjGnbE3giYusnn+E9PxT5OeeoHvsApNzu5TNGSXq0tQSHJfiXSTE0bMXzUrq6KSjS1P7txdFN+6zGcEwuoby08gwmZKwnuDRz973meEWl0dGPcRMObS60855Hf+ORAfUuJ+XhxG92YNG0qbctGsKzM/Ji0NRO5kYESEgFLRzNec6Ism4f3nwW9lRWe/Jnl59kD6cNfpwpDTSaBHVahswSktMc3epsxyQmlfhFqPmNPl90AqLo7o5eQlL3LPk3LKZI4QvVh2vNZu51J+DeoTE+lCbu2vh80hcjBBn0XinsGY2iXbKjtDJzJRRsZapJYp2i7uBqWn6OBHUssmbfmpwmOayueI2AzKORqrlNmWY3Tzh0tYL5HdXrN55l5M7b7PiNWtOf3hCRrh99w780eeZSmKfgQsXL6EbU4ajxCR1rEom9T2pTzwy26LQ8aXju1w/PuKl6Snent/ja0VJFL58a8XFr93lZ57dtNKhkznXb91jfiLsnDvF/OQ+J8dLjveO+fQTiTL/K1x64TOsVh1FEm9/45uc3D7k/tsHPH/lDqd/8b8gP/YEyzNnefmpj/HZUvjpH/oxDn/jd7mlR+iq0M8m6PIEZomdxx7j8P4RJzoh68Ac5XDIzCaJIWfSdGJV+ZOejDKIzZvkDAWmswmr5QIBZpMJExFSJ/TYse7KygjoycTnemC2OUF3znLhn/zTLP7c97F/qmOJUrLdX4G0WkEnox7fLfrmmWu1oSBY2VXWpaEOiXYjpbrp4fJoDcVP7HsehY4zC4NXjPKs9l0znKFIIrJr8pVdIQQHFAoxVeUYx0VZjuGk3icysan/UfeIuWR2bFpVWhKHMwzNlQTnfq3fvKm0AqnDDrwApLMDMjpFy0cUvvGR0Tdn+yXCpk5Ka6mFpSn5QYxVa2ZXQHHkjG284ho4TgSpjcUIhASo1nyfXJYA5Lww9yl1RPZpy51Qb3ca0bVITvNTL7DcKYJI1OSZ4AWJbFdHLkma5teahYopN81ur4qdEYbX/FQXL/xq77pHnC6Rq9tpHIIfPYMrJeegOgW5sc+X/l9/m9mL9zh34TKvffErlGHg8OAek9kGnYp1E1S4P2Qe2d3kyntXOFmt2Jr0HJdj0jBlO03peshk6JSL2zM+LTt89Xif2yd3+bQk7qvyVi4UEf6rd+4zlMIPPb7J2Qk8+tgZ7l9boodCORjYmSSe+uQOH/+nb3D05pLrv3PI8Vdvc7g/58beN5lneG8+sPmxT7Dz8z/PyeYOBweHvPGbf5cfSMJw4xZ7N++wGjJHxydMtmZMvv8znP/z/zjp1FnK3n1UhAWGJA+GJadnW3TDQDeb1uhPVjhZZYZpJi2XdF3iuMw5lYTpZGqHIJzdQR89w9Ezl8iXzjI7vUPZ22fy7h366/fojo5JWzs89s//ZdIPPMWdnSOO1dvFuIxYG2cCmBA5QYYPPEu5JkyaVdUyOP0AUetVW+h40MMSHXG3ygx2KRHRbdGuWslfo2yxT0a0hr+X7QWt9MK4SkB1IDpUWLa32BzF3nsgq9o8mYy2gdc9H+A+OfVpinRAxDu5ul5A4gimqGeNNkex/7AmdR+ga8bXhyqlrnPN5y/XpTjvKjOs5g5M/aicmtMAZgU8wcvbjDTCfMQz+SQOZeWtn8qoD0t267IkCDIbZ9T1FLcS9q4a1klMiUTOkuL9wgO51cQhL971iJ35ux1DdiUm0WWAaq0M/TT3sGocIhnUfProqBNcXPF+TmjzuZMUlBVTzegXr3H4y6/Db73B7bdXHF++xLCZWLx1m5mALg6hswS5ja0tpEA/m7K5sc2tgwOePHMGoXCwPGAoE7RsMDF/FChcnk0401/gW8f7vL5c8FmEgcIVhHmGv/PeHd68t8XPvXieFx/ruHSpQw9WHL23T+qVZ/70CZf/1B0ADl7+JjfvbHOYMsMz57iWE6++u89nPvUplju7LBYrbt29y+H+fc5dfITh4JCTbJnuQ+qZfu5FLvzkj1Ku36VIz6U//lOc/83f5vDNY1bF8ojmwESVXoSu7xnUZHE+LFiuBqaoOc6pMHniHOmPfZLJZ59FPvkkeukC3XQDTULuOhLW7F+OFwx3D8l797l+cZtyZsWy7+iKMq6qT9LZKa/j7SSduSOunIiV99yCQEgRkY1oWlAGhmB6WtF1uPOMFInWe9s/GyAo3jiOeCbJ+algPazJYiQpN7lsnU5b1DdX5TkiWlBpx6Ct/SdmdFs+l9JJTy4ejEq256vTEhUJgercbSulWCA8gmcfcn1kk7eus2hTx9RdW/cXNdrRYgSvqIfck2npSIt3q6IIXQcl27nuJGuobiMx9seO0Xa3p2ptzxUhau8y9RgXX9TIGVJG0TDsiKDUdeRikSzzq31ta6p74DUbS+rS6N8+6f4NU4ZG2qcRcmxcQSRwOmsgodTMEgtGHhonN3Bh2GL2xpw7//nrnHz9NVgVNhQOv/ZNVidz0nRSFZmurKl+8h5Py2HB9sYG1473WYgi/ZSTpZ0I0y3nbE4TnRZ6BZXEpijfs73Fhb7nq/NjVqVjqgMLhMeycmlxxP0vHHPti4k+1naW6DRx+w+VJ/4iaBHKqae489gJd+Z2sOHJkbKxvc3Zy4+zGpTVMnPrxm1WR3Oe/YGnSYcLVlrg1AaXf/SHOX3hLNd++W+z99pr0M945Bf+J3ziH/sTvPV/+7dZ6oKjPFCid1XObG5scXx0ZCF5jH/pUmLxyDbTf+LH2fhTP8Rw+QJLHbxVRscqZUQmpJwpqTDvEuzOYGuCPnmGhQipFOdnaAhZHQ3XlBFhlKnhm6+5RjDa7FXuIvhhhjWOJ2rIxP5MNVm4USQRpjeXS2vagj/JKYdk3S+0ZWk3xRc/a1BPaXl9VQFKJPfGnZ0HIrgn/30ddPCnlnMUkXXRBDr4WOzWkWjaFLN7FQyhwxH5DmrfwPidlDpINiFKVLJ7HoUMWDJkbYxA8Sxt8Loy8J40xZr6l1Wta0Ub7BX1/ive2NyOXRI7gFStna1NkL+DtvcMBRcHP6LWpzkECcmjaKGiIpTs6KkD9fOuqJ0AVrR2s806iiRXcPjn/A1qgS4OvWv2kzWnzxaZ6RCmw5LdPOPd//A3mfzeVbaOgeMjlicn3Lx9h7PTKXM5pAwDQ0mWrW6a3cc+MAxLtmYTJqrMh4HtrU1repYmFKBk0CQMWhhWmb08R1LiKA+cLZlPq/IZlGVecVUS9xFuLgt/kITdac/nLp/h+ce22NbM8M0Zn/9LV8nb5zlKn+bUc0csr17h8P4++6uBnYuPIKnnZFiyf3DA/Xu3OT0/4emLj7Az3Ob8i8/w+I9+jvT2Va78yq+xWMyRkmF1wJV/599l53M/wJMb21w/XKJYg//Z6XOc3L/DZLqJHB8zDEt2ZjOKFBZ//EVO/5U/jX7yWRYZaxMbBkIgaWppKgq1fXAldi35w9bJsumLl29Y9xk7qsvw2NA+F5te37/Rw5tLbhwlYWVSLrfN9EXAwzialLQpi+qq+R01gklOXldXqatunx355S1ynCttrmMkXIa4ukJxua4GWTJxUEY9AboS6K7YtFg9nnidaVVifh+neJLTHfb8CBrZ3lTxaPh3gpQiEpVLtl49aWIaHEuJLzpYhqv4yaJR7Oeu0TB4e1vUGrshlLJAsR7PfW/QLlwfsy2lZn8aNxPnx6sJsocb49jugK+SwkLYgq9XI4eSCyvoUxnRv1ywQwYtu9fAnb17JIOZtg/yMhasQVVlVP7iUYbkbueQVvSa6VS5sEicWZxj/zff4OQXv8lmmqF5YDt1qC7Z27/PuYuX6KRjkhIDAzlbM/mEweckwkSVp+/v80xJfO3khMXuFqkTbs73nR8rHJeVoV0RZqmnk8L5yZSzG1PurxZcVXizKL8ryg0v0pykDobEK1f2efLWPs/vzPjc9zzD7N1nWb19lwt/4VHOphPy8cDqYGDOAWcvnjO0PCj7t2+yffeAHzlzjovTDaaPnuX5l36O1d5d7t6+acmMk0TJmaKJ7uQY+erX+PSFc8jyhMNhDqWwtbVNWS5QXXBmd5thWNDvbJH+xIuc/V/94yw2Zl7kWbxpfSgIO5LLEPk4AsaIxxQvGwqZyRXV1FbMTEhMXF5GbTfSCBHhdIQrNPyOgX6Mx4nE2qbUIBoPhjEfF762Rn5RPzJOuB3LvCkY2/SKH6BR/P0lef+x9fQXGf07EMHY6AKu4IOukDpviuX9ITLiRKNQxbyXtVZE4gXrJa098zsqyI3WB9kLQld6QrSQLV7ZnlXRLHaEryvlooWenji3qkT6u1rYM6BlZKzaKbG2qbvasjPeIaCU/Wen4boDG+6UKnGCqHWQXPfVo1JZnO8Brxb3BleI0EnkFjkUB6LHeIXDBKprVicqrKOncpd6Ij0ilwHVFRtZ2R1mPLI6jRz23Pz1L3Hv179Av3/M9ukppMSwGkiTxHJYgkAnHQlltrnB4VDq0dDSWaZxv7/HIwdHCMLB4SG/dHKPjNIpTGXCpJvy+HSHnenElJK7vIWCJb/vsbea8z0iPN71/JqueBOlaCKlwqDK6yu4cveIg1du8JOPXiTd3+PUvUOmxwsWtw9Y3jvh3IlyaaGcu3ubywo/t7HJYz/9Yzz++OPMLpwn37rHjS/+Ifde/RZyskL7jhvDgpvHRzw33WCSM/O7t9m5eIkfePY59o+P6YdMnh8x25lR5gXZOMWSge5Hn2H7f/HznGxOvXq+YOe5WTQsMpLNaFlRthatLsya5a6RLq+PVIu4SopoUu+fd4Xl0aro5BhdI5N0jItWUyTU+obvUu9pNZ5G4qhdCh61Te2+0V3Ax1AzuAkaAAzNhSIJGsX4qiFnVAdyzuQg11NDWUGNNOXg8owbcHtoNbwRNV/LH3TFl8uSaF5oVMaEgmWKW/LyCjPPiUqEu1F/sH3035NSGjx4lHMhl5VFwoR6pJGqWpi0DJRo+qbmLy/KYFG6vKxumEUWPGO7pr0bR9L5yaSrMj4wYPDw+ZJgeqw9r3hrieJozrwunOgTT/pSrMF858dAF8kjf93ymJKfeJJZevJjtFqwwwFT1xpYGSw3Uj9865KtMyGGabD650Knmd1VYfNE2H7viHR3yd7tu9z7xmscfONlZkOhG1Z0vUfqukJPx/FiztFiwSQJy+Wc2cbUjsdeDAwoR8OSa0cHvDGseD5tMinK3b7npbMXmTFwa2+fTGJrsgllRS/CVj/zMVl/HpVMB5zuJ9xfLXkyK3+pm/IW8IcUbquwSDAReJYJf/Kg8NLxHb5xvOR7fuOL9GJIR2ZnuL1asbx6ixkTnj97ge2NGen55ynLBbf+8PPc+/JXyXv3mPYdd7rC1b09VgmW0wn3JHGpm7KYz9Hbd9k9nZmuMmU1sNqwQzxnGxvMdjeZn91g85/8WfZOTdC8IsdagyuVJdL1JDxipytD51qrK23zJpMrC6RYDk7UPZqSaK6UuAyF0RG1FiBBgpccZ6PVFzFdR6SfUPtqiQSOj3srOixdznPN3wt0kpJFgatysNifF447wy2e1lLb/7iydMWr7r1EZ1aKQOrq4az1wIH4DIJ4L6YcETRYD1b5JYo/a2U1msnUSS4BWux+RQKddaBWMlZY8WHXhyqlP/y9K/R0SBGkd4IqeQIb3jQq4a7cykji5DVriIXdS0Jkw1wqX/iEW7aEHQfj4Uo6h5MJ+t7Oti8Kq6w2WSJWtjKYCqSzQtnoDmmLOlSFLyKcHM+ZTCf0vcFoW2ytyExLoeuMEJVknQUm2rlAdD7eSABVIrkz5CIbXURPR5GeE3rOaOGZvMnZewPD3QVf+xu/h9w+5HS3xdGNa+T5IWl3m4kUCivKkJl4n6eVFm4f3eKJ3fPowtqwdJOee0d73Dg55Gi14vRkyscuXOJbKuiQ+cbeHmdWK3ZmPZd2d7l9cMCQT0gIhycndDs9066nV5vPToVLO2fpT44gF45LYScP/FBKfB8dOcNMOra6jsdmW1zoZuytlrysyoXjFb3XOh3PD3n84kV2Hn+WrU88jtxawvc9x8lbb3Hji3/E/M4dEsohytV79ygJzpw5xdnJjPuLEw72j+hOnUWk4+ToiPlqyblHLgFCWazInTI/OWL33DNsfvZ7ODj7cRZHdvJs8T7udupNV9dzdKyNJT56dYGV7YTlH9ydlxaEEMuJ61JPlxJFJgGiWQ0D2XNziD5bDp5VG5WQPNSevBd3IioIPLSegqowzyHJxGvSxAt0nR4vyvJoxcbGjGJVx66EWo6ceTFxqk2iFEM4Ofspw1jKR5es1YomGIZVdUdJlv5gAMnmoIz6XJobG1UTCdHoWGD7PaUNR6MT0IEhu+JM4vf03DA3Hl0n2GnHrYPB35dS+nf/3/8BWsxnjGStrNix0jqQlLoAxXM9IjnS0KxV9lvGa6KI0E8Su1ub7B0eVouTJCCd+Z5dSh4FK9VdchNkvnIu9DPjrAyeR42Q0nWdKY0UPZ2oQilVcQX5HdbWjwZ3U5DcX+86QYmEUYjsVcEOHxQtlqiHMtvcZLVc8Hwp/C9//uc5vankd2/zzh99nTu/80XOXrrAMJtz+9YVusmEjamdz75aLdBhoMsDW13HIXBz74DzW9toyrx17yZXjo8Y8sCjWzs8s32GqXScmm2Th4HcKRv9CXvHx1zaPMesF3amMw6WJ2jXsSzKjft32N3cZkdswyWBzZR4cuMUj27scOX4LrvTTXb7LWaznmmX2CSx3U3oSyLpkqNsm2ZjskVPYrVcMesSHRO2f+yz8M4N9KXHuf/bv8/eN1+GPNAl5bV7tznq4OLp0xysMrfmS6QI27MtjroFRyKcO3uOfmOL5fEBt25fZ2t7l9O7Z9nc3rWExp1zfOWdW/zyv/lLzJMpgQ5BuuTxVEM4ydFKuNbZwqm1qLpPRhqru9rRkQItFtlMHZOJ1aR1nZeOpM6CKEno/QQSC4hEHhvGsSTxEqTExPNzHLy7gcx+mGayk3FS8pQUQz+lrCwopCanpfz/SfvPoE2yLL8P+12T+bjXlu2q9t3TPT1tpqenx3aP3cXuYhcAATIAkUFSXgoRXxAKhiKkkBQSQ5QohRjSZ5IKBgVQlCEJLSEuPHYWi3XYndnxrqenp70p+9rHZea9Rx/OvTfzeau6GsHN2d6q963HZF5z7jn/8z//E6nqKq3/XOallQgGwTr9DpuMZNt14NTIFI0vZ3DJCTDGaXY8h2kYtU0WsKon5r1WUvQHr8G7pFNmFKeSCE1olTeY9iQWrK/xxqnKqyhOF1JFhvcV3jmczaU+LS89/d/QKMWYT2+FbjOS3yKK1gMuqhWNSClgVh6GGpnYqapADm3392ZMp2OOTlY0IVECIiR9BUhth9Q+2PJfBtzG45omNCyPO0QMOKdiUzFigmCt4Co1oE1I0io5tLOmD6pTJXQON60VYjTKni6xPajOTRrolLQwgJMWl91qETha88S65b/39V/iQtjhzf/871Ph4YNrtM2a44MDts879qYTVq1O1mq1YtZNoeuonWfqPbN6xMF6xY+uf0ATOtoQuH865crWebo2EETDZ+dGYGocge1qwmJxQiuWmR9xbjbCckJjI61rWbeRm4tjQj1hx1RM6hobBGM7tvE8u30ftfNUlcfXIzyGyrlU0WOo/TY75ghzdI3gR4xRgTTrt/AvPodsT1nv1Nz+e/+Q9uA2lasx3oM1rOMNrp7fZ2o9v5gvOLQV29WI8+Mx+xcu8P6NG5y7eD8z55lNxojAcjnn8PoHdPsNu1cfwO5f4E9+8WN+VI2Jts9Q5VAHMnkvJTMSTtJ7QwnnGYQfMTtUKWRRTSMpMAFWs8hOMiaSviZlusygZEhCKuTO2LfJMEDO0g66xuZDWyzK2lbIgiBIEHylEihER5a4zemTDAr1af4EUUf1jDKBOcuUiE3IUUyvC7EYDfXaNCMcEZwIk8mE5WKhdsalrtcpwWNsgvBQfSnJbHDdQJpsSAqsNo+iZGJxHpf0CAL/4//Ov/3fzCiRQFzvK5pWN5/DFNzKGlOKYlMkrd5UPoFQnlMCenSdWHjs8fu5/8p53vrgNu+8faMUH+aZz1T3nuXag8/L00W6L6UbhNxeKA0gAl2rcX8UlF4gA4KXxDLJKrimIaHkKS64QPLQY3JJFUvPKxktJ0D7wRP4ymjCX738CJdDxfG3v8vJN3/A1oVdXFXThIBdNVgx7ExGhG7Fan3MKq5YLBdM61pPUwfzbslhO2cUPc9evo8dawldg7VgPHSrFU0H1glTP8Vay8Vzu9xuV1w/nTPdv8B0NOKc8ZwsTlXR0BpGVWB7ssV2PaaKIJ1KrUpSU3Drjtl0xKiaYEa1iuCRoiGxXBxrpfk77YLH6x0w4P/KL8H95zj85vcJ3/kRtTVU2/t4CaxCh48w9TXrLlBbx31bOzTLJa2zHCwblhI5NLAWYexywwjD1s45uumM5uiEk3fewz10lfe7iFQ6D8EMMkaSvIIC0GZdLMGWjSDkEzMvM322zCNSkrA1hs5IErQjNcTIQLOGJdiELyqaTm8a+oxsNowmlSVFMYAvB53+p/ergLklho5mdUpYNIwn24wnO1CSNpT9JElJQg1cCh3JP0sZQ5vuN5MKcuOJLlnmTBWS5P1HDGHeYKmIJhKCgtqZ5xdDykQnLSgk87UsRJsKkSmennNOOUvaSypRFoBMLbjHdW9PKRhA0+suZaayvnGuZG5D2uQ2DbVklUIp8WeeDGstR8dH1NWar/3KJ/m73/hj3nkzEoPGs72M7pCgppQEC5iYuoUm11IbBepR0iVgTaXxMtoPElJaNIV3mXCWgcACSArYTEdIKdDS1CACRjMnEVG6vINJhAfF8rnZPr9x/jLhvWt8/0c/5sEvf5ETWeJWNeNOwe/YKT/LGsPubMbN40PqUc1qteS0WXF7teSdk0Mq47g82aENgaYNuGlNaNes12vq8QjnDM265XhxhExanPM0baQLa65LSzyIPHXpKrWruTS9QCQkQ5yIbzEZcBHECJVz4CymA/fsM3DpAs7Wig3WI3A11kC3WMH1H2EefJBw8TLuvj2ODm7Sfutb+PmaanuLEDpCs2bRpM4g1nNhtsfN0DLav8AD1lCPF3innpoj0o0mvHp8k09fuIILyrmx1jGZTZntncNUnrePjrnpHBFbgNRkg0pmKLPC+nT88KAjGZLUoTh5vboQLCHhmiH268Gk15iMVZnsdWSekhSPrDR+yN613oGu/ZCyadm/Kyl93R8B1ScXq2stdh2nx4d0Tcd4soVY31c5pKxbXpflc8gBQK5QGOwjkexqpaRRVAVNkgK9KGUkH+4RksxIRIK2lqqqiibk8hnd61Vd0XWqZ0XUveUrR5v65Vnn1CFJo69/mGSI713/9hGeksadIcm75ta8RmzCWnrehfbkShraKYNmRMWxupj5PcJsa0xsW37yk1d45933UuGrugklxZ47QJCNQwBjdQPlCUE5TYhJWjGDEDJ1bnDOISFofiSdCMqNSq5oArBD6PTvdpM/YdIiMjHxLVySxY2RR6PnX97a5ytXHsXP56yu3WB+cszp2+/wzj/6HSrnCG1D0wq71Yi5rBW0NsrcrX3FUbfijeNDFqHjvq0Zz128iAlwYz7nWtvwxsENanuOiTU0q4ZOomJmpqMLLfPVku3phLoy7M8qFqdrrq+POXdguLx7LikgNoSugSQ4ry2eonp46ZQ1FmIXuP7bb+Ci0goE8M5TuUrLjZyjOznm8NWfsvXBu5z+8QkxdlSzqZ6W87V+nvfYusLXY7COi7M9VhI49lPWxwfs7ewx296GVct8OeeGP2HRRdZi2bJWE0QpJJJJRf3gVd5/+11OUipaTL8xNzyItL50yrL3nn8uuzLtZMFkDS4BsTnuongmWFuwRUkGPQV7Keukn6swlhQDmcmTGU8iZ91E22rlqxgWk7wYMVR+gktES+s80QjiUAOe7qvUF5jem8+rNaZnK30GB7VnIpIgGP177KNBTeDkz0AwEjC1RwLYaGjWCpWIyXs+0LQNuTaPFCGpk6DfG1Mo6Y0hdiFxlhNf6d6O0kfxlASCDmYbtRbNZYwsD3AOn3IdWXmzPqS0nU5ocndPjxu++d23ODo5hVgTUVCtC8o/UEA8lhFTsSoFHGM+xZKBEQPjekQIka5pdEAzQHnmwY0xuGS99b16p6V7bjrtSuCbMg9ZE8YaixGLjx1ftp6/un2VR0ZbNO/fYHFyQNvMCc0ciR2nJydMncWEQD0ZUY9q5qennCxOqL3jYLXirZMDDpsl50cTLoSaKkIlEaRjbCIzazhsO149uM3Hzp3HOMdytWQynlCPPN06sG5bqrVnMvLct7vFcr3G+oqdac16eUhoGmJY9ydcDnHJC1QzIqSsiamUx7VOYa2EBhsaXcBoS6Dbp9eoVrcxApUfAVCPJ4y3tvCjMb6qVTAmbXgjhgmet2OkvnCJqh5xeHLKB/NjPv7A/eyeHkFdc2txzPbeeZyInrIplOLKBV574xcsR37DCFlradsuzV9fJmJt9kRM2bxDzpotWGWu+k/eRMYcM94ifeYub36NPmI5rPIyL96alFLU9BWZ75ay8XLnbrRp04LBVzX4Wtefs4i1hJCZdaav80xGMa/bssYR2naNMRbv/YYBMMYo8G+U6W6dgy6UcFJKB12jpIcuYOOQpCzFiAlGi9ux5OKNPD7epTDVaRidoRxJtaJ3KwY+e92bpyQxaWULrshYbg5sZnDmS4tVI9b3NWQahakFXa6E5XqF4EC6BPgZnLEEkzFvU4ybSSdn4XFkfMfopmqaVsPW3FyO1J8zGZtS6mF1okpjAtuDcfnPsuCRXmHTap2Pj4GHrOVfO/8onzxqmcUR88MTuuWSdn1CCAsMLVuzilurOTv7F5gf3Wa5atjd3qVqKn5+431uxQYr8OjuHk/s7CJiOF4vuLk4YStOmFYVF6ua8WqNOT3mOAqvHxzy8P4ulRGarmEyGjMdjViuGlZNx2Q8YmwNj+zt4KLBrNes10udN+vx3qXNpQXDYhze+BQGK0CrRNIMXvZhtyBYSSz9tqGqt/C+UhVFidikR92Nkx66tVS+ZuQ9MUIXIlfEciKR601DM9litDXj6PA6P3j7TXYksDeyHN06JJ67gAvJA65HMJsRt7d5u23w9ZgmScWAtv8SEzFOG3kaI3jnuHTpMkeHxyyXywR9ZKa9rt3cx7D3OSghu0ncJN3gpuCMuRNN3qBDBnQmSea9kK+8jqP0/B9JC9owMCYZLjAqyp/XapJI1Q2avJx8DRneg18C6s0Ypx5n1jDXz++Z3AbBhFyKkj7fJA/QgMemsHPoiSpWZmwSkkvPXspYTK6YS0XAWZoned0W0+/rgSG92/UR0iWCxEhIYU9pz51vcONB1RCETOSKumA0HEuEyHTKiFPimTGOaKOC58YqjySDaNlobGg6JQY3vUud8w6a6lavajQa0a0b7cCALkyi8k0ynd87m1pm66LLxkusFOlRjOCwTNvA57d2+cu7l7l8/ZjRZMLi5Ijl/BBiR8ea0K1AWranNbdP5xzMT5hUFQeLU95ZHnOaav8u+Ql1iIwDxKDiczZGbIB3Dg65vLfDjq/YGtc86vd492TOzXXHteMFD+xtEdYrmrZlPBojNbRtx3yxwoxHSmrsGtZdgzd68npfU7lKMTpBw13nMCn1G1HvwiowoN5/SjxoxiVjFoYrkxU3Q8fj+xc1syMRaVoNLdcHLDgiOqs62aMxpqoZTafUvuZSNKx9xY3bt1nPj3jy8mXaxRFj0zJ1wrVmyXK9ZuQqJtvbjKYT5PFHuHb7mGu1J9qAEU/OWEXAVx5t2Sfcd99VvvpLv8oLn/kc3/id3+Eb/+C3aJoWEcWRJFIKpPXSkp0CPg88n2JkTG6Qvbk5Meo5d6iRzKZo2AkXkVQupd5VpqvcsR3TrhVjtK9iQeLzn/mP/tAs+/PMz2IsLnlauoYz8F3gnCLUoeFcfyhn7Fnveegd6T9kfKhnd/f7MiTYJO9vmxdRKl2KMeBTAuLPHL7l9i4ZhxkMRxmQmPpsqTqjKzcc80ObFLNbJfppOY9VdjGCjZa61gltU552aNXLgBdjmGY6C6ln91vvglxd7pyj61QUzkQ0NIkRi6iLmdKbVbLgmTdbBUNlDCPT8bAd8fwDj/LoaMQTN+ZU7x3gJzOOD2+zPLqJ9QaItM2SGNc4I1gJ7E5q3j49oDGGg/WSiXU8sr3PTDTEPQ5L1m1gd3cHaTrGoWKyM+bG+pRf3DxgVlXsjUZszWq2KsdRGzloGmaLlovbM1bzU7quUy3oEFisllSjiklVIY0uoHE1xjotMbGgALJLGSo0I2q9pxqPMDESmlazVVFXRXa3cb3XOvY1B80K50aYyuKrCokwEg3tTBfpuo7QtKyXS1gtWJ8eg6vY3r/Adhuotme4aoeDWze4OT/m0XPnuXZ0m3o0ZTydsjWaIsAS2PvU07z5n/8dDnytnkOqLzSg6pTGsD3b4sXPfoGv/+qvc/nKVYxxfOHlL/OTH36Pd974BdKlxIxJhxNZRkcyzo0rHpIp4XsJ1854JMODOIZIMFq26zNe0+8QXZEpW2Zym/VsBPJhnry4mBx9G3I4JL2hSPsw6gds1LPlz8h4Vj5gC0o0MKbWJRpAwn5MShiJDMjEOUYbfO7wvocdo/PvS3KAbGPVa4uCtlE0GnVZY84U0t/9+ui+b9xpHTcrpEVPL/pCPJNcQVXg6z/PZh1rq5hPXRvuu7zDbDri9u05tw9WRVL8bha5FPvF1Nwxg+kC3nu6rsMIdOumeFzWaCM/A8Qu4qzDoDIpYwxbEtkSz56veHA64/GLl7iwt8sDO3tcevBhxntbnPynv8Vq3mC2t1geHHB6+31MJYQupmxOpGsiHYFb6wXX12uuNUsqDBfHE6TruLU6ZbJ3nroVJgROV3Ounxqm9YTJeMS2MVTjmnUbud1GTts1V4G9UcUD1vHeySkfnJ4yqh3btZZmVJVnMlaBs7rydCFQ1WMQg8do94jEUJaiKZ7DjzQxrZLuOu9ZNQ1jgZHz2h5acqZTXXbvPaazuHqErzx+NEHGU/z2DnZrTLx1C7tcEK0ltA0SAzEE2qahXS2YxMipBC7u7zGpL1PXM64f3eTCaIsH7rsIpwui8bAzYTSd0onjezevsx5NVP86HUJWhLr2PP3sJ/mVX/9LPPrEk+ohpE176b6LfOHlr/J3PngXWTUJ3CcZnHzwARJwRg/0ktbPWOZd9kFfZW8gC/nTe1IapqQDNH2V8QnzGuBhZ9d3AdFT3ryw0wefm5/tww7rbKwxub4uGdeEE2mInrBUq6FqNr5FoprNexxCM2f3fmnwIXrfrjwTySbYBHjnspgB9vRnCd8yBnP2poc3amx/I8qqTbG4TWn4dCeVc4SuK+lE03UYa3n/gyN1XzMZ01hGdcW6aTbupRgoa5KW2+BEMykz03UqD+IcbRC8V5F/iWBCYGpgT4THRzOeuXAfH798hUf3LzIZTxgfz/G1o5qfIouGONnXOqF/8M+Jbcf21Yscv3uNg9vv0banOHLKUzGym/NT3lme0MTI1cmI587tc3yyxNYjRltb3Do54me3rnF1NGPqLHuTMUtpeePklHmI7NdTzs8mbG1NOD6e04njuAlMRjV70wl1VfH6wSHXjo8Y7+/h65p1s2bkPbPRCC9C5WsqU6Gd0wUr2ptr0XTMqhqx/RgLhlB7DiRw4+QEJ5H7Z9vMqnHyrHIIqx6zF2X3ji9e4NKv/znsbAQI4hxElAoQliw++IBczkNSYfDOMaoqbBe5tVxyY9bSzE8ZAY9duEJzesw7b77Bxf19dranmHqEffRBTk4PebtZw2iCc14PExN46OHH+OVf/Q2ef/EzVJNpSn5IXvF44/j0Zz7DD773bX764+8nCEFrybTUCZTLY1M9W/L081pLG/Is3tiHeAm0RXWZbC74Tptf+U3q/WB0vQ5DpeHmNlYPakc2PlKq+zPVIK/xDMhnrItBSLdhnIahl+lxsqx7FELsjYfe4sbzbey3wc+KOQ2OtMxqh4GHJilME1xlkU6hk2zmi/G8x/URjO4surbpMZUPTw+cMxXZ34wi+NSrSo1mZsTqjYegqfzQCcqDyq2cNPxqm7Y/lQaDrPfQ42Sa8eu5RNZXmt7O6eAuMLaGy9bx1GyXF++7yjNXH+LSbMZo3sD8FN58Tw/IkyXu2UeJywYzrmC/Zv2HfwI7W8hRzcHb73Bw7W3miyN8ZfHGsmpbbs1PePPkkBbh/umMy1VFZZV3VW+NuL1c0khg5CogcHM9576tHUbGUofIubrGtQ3vr0+YxxWzyjCZWrpOaI1wu1lTu4qZc9y/O+PdozkfnJxw/7ld1icnSAjszGaaCQmRYFswuV7PssTwxuo2T04uU8WAcxWHYvhZiLx6umTPCJ/a3uJ+56k7gS5pWIVAZ6C2Vk9VZzXMu3WbxT/4x/gAMYDtIuuoRMwWQbyWdXQkXNCAoSVYz6Qec9k5jps151zN6ug2P3vnFrPxhCeuXuH8uX3EWlbbE859/Yu8//d+m9uVRxubNuzvn+fLX/klXvr6L7O9v19A+VyvRVqLRGFvb5+Xv/xLvPXm65yeHCYPgXQASvI6kmckucZr0zM5u/aGCZ28EUtHj+QNxCiISz8n78fJnZs876chdpS1ke6IUEiJh3RntvgclPcP9yZA6Lo7cKDQdVhjimd2FnDO95d5gMaY4mVm7E2AmJLSJiQytSToxNqUsdTDejyqmbdd8pLSeP8LXP8CLZaSXUyWtfRMox/omADo3MbI5Vg1aQdIiKlmDjAqsWCzdITRyXXWYiJ0MZSKk6HFz6FEqvajUNyjirdpbytwIbJtLI+Px7x47iKffOgRHr5wHzMM7vAY3rtNPHkTYofdmUKlvCl/6RxdY2kWp7jHPsbiD79PXC64/dprxFVDt15wfLCH6f51wtbv84ujP+KdkwOmzvPI3jn2x1PWqwUHp0fsbk3wEqgdnKs9t5sVYKiMZYXw7uKELV8xSglk5x2jcc0HY8/pzh6tsVQYpsZh5nOuNy0XXcV4PGWvi/jYsTg+wgOzrW1dRAE9CIxm2UQA73l73fIH0zGTusYs1nw3LHjFWPas58+Nah4HqoVmqlbJ03DGYFPNUgDq8TYyG3N/XfGzV75Du72HP7dPPd1GtibMnCMeHBMtyHqFXcxVjSAETTaEjqZd0bQr9h188Obr3GoDe7Mxn3jgQS5u7eNMJC7WMHFUVy5hRzPe/+ADlqOK2cTz7Auf5uu//pd58OHHCzk2yp3hTF6XYHj62Wd57vlP880/+meqWR6Tl0C2GRpw2Yx/6KoHSaTGwcE4BH1z9vbsIR2TZyjoweiwhQ+WcdK7YVR509/NMysYqjEJTB4Yk7tAHPkqVBdyRKHJoP6zN7PmOQLK7xtGR8P7tHnYjME4SaJu+pmjcc1yuUyKlIbVfFUkd5yzVFWtmdruz1CQa4BOAkjKDCApLlWw0Fk9nbUnWjpt0CpnYyTLDCNkwanMa9Cwz6bTBQwSOnLiU7I7nn+wPUtcwTJJ4YXBmZpgIltdx+OjMV+57wE+e/khrs52GDctsljQ/PBVwmKh1cldxNgKGdcsTuY0q1tsTyeE9ZLjn/yEU+dpXn8DOTlGlmsCkWpSc+P6Aeb4P8XEF1nO/zK3q6/zse09Lm1tgTUsFnMOTo7wY0drgmZ7RGvxZpVl3gSicez6EYuu5Xi5wiGYesyb57Z55eJ5jsc7LK2nswZvLW3X4nd2GRlhLB1bQfj4ZMRTt6/RdYHRbISxBu99Ov3UIOVWTlEiH7Qtvzeu+NPFKcFF7hfLn/cjXnCenaB6QHa2Q1VVWKdguAVMVWEff4jqmSepL1zC1jX25g2af/cHuH/zX2Z87hzGWELT0C1OCScndLdusfrhT+k+eIfQNUijyoshthC1JMlORpzbnrG/c47d0ZjYdZi2wUxH2HFNmE6ozp0jtGs+ODzg4aef46U//xt8/LnnqeoZmJiyO/q0yqHqN2m/iYTZ1pSXvvQ1Xn/1J1z/4H1iBJ875uRgIx1+LikfFIwobbw+xOk3nzpo6bVZMz5/d/q3QgPIn3MGQM7XBlYj2TvbxIIzo9smTDCHdBY2DMkGqJ2jEzNwxtJ9nvX4NsZO2AC9h3hWwdpEwX2ToJTcBLNZrUuYJiJZtLMkpELXKR/xI657h29oo8e4Ybl7ZYAuPZwzPVM0D04UJTKG4hIavEsTm2LR1Ek5eVWmlIHkMtwQNc530dBmeRIBrKEW4XIQHhmPeXR3l5cf+RiPz7aZHJzA6Rq3OKC5eZvQLhGi8i6cZb5e0TVHLK+tCE3HeDxh+9J5Tq7f5PDwkHaxZEVL0zVcPz1EvOPdt2/QrCueEsMUqG3FU3sXqepDQgzMFwsOT09x3jEZjVk3axaimksVRiVwK0+XQPophs47uqrmjfsu8ad7exyOZ4xspfpTMdKIgoWdq+iAFWMOfMfxfsWl1ZIrtw8BSxtaiIHKVHjjMAQNt1Cm+2VjeCIGjp3wchjxlarmQifQzekwaL8ww2opVL6CoHFZNEJ1eAu++W3oIrSBk/WCcHLKO//e/4WpMWAtoe2IMdARcKLaWMY7sNqexzqH8WNloutW5XK9hWsjkQZTee166z3GeRiNmH7iceJozON/9a/y1EtfZby9m7JRuai1v4yQ2MJ34jVI5NHHP8bTL3yOg9/++zTrRuscY4QOVGvepPZAlBS+NT3tZGhASjhETuj02atCLcifkaILs3G36bZE7vC07saXG142RSJSfr7zM++GCZW+jUNM58PwIkj6Y27DCIcU6lkZhJQSU9hmNug7an7SIOiHI9KXsJQs4j2ue4dvxlDVOY2crbF+sTbpUysd0uQ5oxyY9WqFTQ0HciGgpqMjPqZQL8XKeoh0yTBpv64YUpO/NBkBnWxLYEuEz7gtvvbQozzlJuxc2KM5nCOvvEWzXnMalA+Uwcd1u6aLga5ttQU0SiHw1lI7T4gt737/R9w8OeCoXfDe6QHHzYJV2zL2njGGXe/Z26+p5H+JrP4SZvLbmOqAJgZOl3NOVwvECvVkzOl6TTTCcbMiIuzVE2Y4KlGp1c5ArBwnOzO+f+Eir822WbgRFsu6W99xMkk66tYEvBGOfcXRzjkePJoTlwIzdcOj7QgSkvSE0zrBKDw+9vyNlLDeso6qU1liEZWpiInfFYmI1bDEisFJgHWDyVpFlUNCao/lBFvVOO+pp2MoKXXdqCGG1DiCBD47XKUyHMYpUdZ6h3UeW9eIyz9XsLOF3d6F7T2ufu1XOa4nBdjto5bBRpc0VtlRGW5MDHVt+fwXv8LPf/JD3nnrFwRRMWeT+5kNSLQmu0mQirT1eUSMgtGVSo40zZqcaOmbtZqETSUgOEEZwiYMcfbvdzzPXX62yQu2OYyLccNobHhGgzG42+eeTfNv/JxCxOyJkvZ5TKRarYHtmd8xaBRTBPcM2CyOJ5kjlfW+k834EKM7vO7NU0oC5dp9wKE6QoIQCV1HG4R6VKu+TapcDtKVkhMXIYhQIZzf2ubKpYt86pnn2NrZ5bU3XuON197g/Vu3WK1XKq+QJvb+K+dZLY6RqEWYJ6cL7ouGr073+Gq9w/3TGTtb+xz++Ofc+O4PEWnAG2xV03UBFzRj2EluZqk6MlZQMheGpo1cmx9xsJpzfXFEm+rS9scTHprusDUa40Nkvl7ivMNYIfJd4tYPsM6ybBpOlksWYY1xhto7mq6hE2HeNpojNY6bVrg9nVBFmCxWRGN4fW+Pb164wIGfEL3iP4FY2jblic98lBD1VIpJC/2mHzGZTmlOFgQXmW7PsLFLaWftwRdtBiI7tlxAosGKpxPVmnLYhJvYDeKedT6BkjXGeg3nnKXrWrzXU9HXU1xVKV5gBeMtznkq59Mpq59pRA1jTPSMNnTJo1GdwyGZ0fmKWDlGD1xFxlNwns65olbQW4shGJ3CuDudkbJxDMLDD9zPZz73MreuvcdivYZ8kluVz80Fb6q7ZFIjgn5TOk1BauiRyyaKxc1GoK9/y8D3Wajnw/Cf/G8bWW5MAbaL0UCoq4q2bYsXlD2fD0vrw2Ym8ex9bGQUjVZDkCSEh4RnI2fuJeFkYhJWLApXqKfZk6yzsUKSBluKsu51fWQzShGbXFyD5gBSnY53qeuILj4TyzJJWi0RCYaxgX/jL/45fv03fpnLly4yHk2wtqJ1ltNFww+++wN+82//XV555WdUYcmVesQnLlzg+S98gQ/+5Iecvrdmt53wucc/xs7tY07ffI/T9fss3n2X9clcM321MseX86MigZqxLo2RhVVomLct750eMu8aTpsVU18x9RUPb+2wXY3wSThLYqSTjtNmraRPAQkd1lkaI8zXDYu2oZGgraQddGhF9cpBN51wXI+5Ppvwvh1zPN7BOMeFbkWL8N5oytpVughS0bAkw54XeB5L1U5OGEYMYA3Xq4p2MmXUdjSLhqWtmE0qDW8gbTKKno6mqi0hnWI2ARJGTKnoxrkBWc/pXrUV1lfYyjFyIwIVtauI4zGz85eJ7ZqwmCPNmub0lLV06jWTWkjXyuKt/Ei96LrSzIxEwqBSXBANzy9cYvzis4h19OJ6UnCUTS8oFcWYHDJkN4qB/dJxcM7w4uc+xw++901ef/UnOrpaOYPB0KGGxujDk2nPJo+dZBJA/vezO0XK/4q8h9n0ksorzzxHb3DSvsmel+0xpuF+zAYJ+izZ2c90zuG9Z7lcpvm8u2cy9K5E2cwb5Sz5MLGDzxgaM4HCEzQM6ik3Ss+yNzkoZbnr3fTXR7RYAmOsShc0TbJ6Lt0MOKfMbIy6dtZpKJDbdwuRp++/j8fP7/D2t77N4vw5Ll6+SDWqqSdb7O6d48tffonnn3yKa//vv0/91vuc/8TDVPMlvH5I++BnWLXvcPjqH2Nb4XQZWHcrgolwfEjXtNTjMW27pgstbbtGHTZh0bYcrJecNGuuL04JCby7OJ1ydTZl99w+VSpODVFxsy4oPhJEaGJDm0MSEcQIoWtYxUAjWtxiK0P0nrWBo7rioJ5wMJtybTTmyE1Z2RGdRIzT0+x2NaJzRttOG4qUCEKpzM+nsDF6BMQQ8EmTSsNbw3UxfDCb8kS7Yt12rOdLbBCmYw9W6f02HVExahZIj+2AiCWoKp8aqPxv5QREDZLRMoyuWWOCsvHrCLvViGvNKQ9cfopwusCFjmp7i5jKhJax4cZ6zU/XS36xWPGitTwugXbVYhYLwODqGu89waSOIVVNeOx+dn/1KxjjMZUnus1iz+GGSAuzgLi5c2vZBHLWG4ALFy7yuZe/xrtv/4IwX+lBazI/KdfPD8xb7AtgS1EqvccwvER0rvp4lWLEjGyGaUNMZ+jZKNTRh4JnQ6wqeUgZ2D5bb7pBBziT4TobOt7NUzIJM8pSJ1nr+6yXlV9rsjOSHlQNtn5Xl8q5jEGL60nfn7iI/s8SvoWg3QnUOitFnxTbm5StcGiWMprN2h8nlkcv7vFXfunL7OxuE0PD4fExy9WCunKMRjW75/aYujHt996i+ie/z959F5Gf/IK3vvMd2hgJJye0ywXWweq9BbYe4esRJhqa9ZpghdAuaKPKeJx0DbdWC06bNfOuYeI8E+95dGebaV0xqUbqFIuGd03Q54oCnajcRRdbOqCVlmisah7bSBClNYQke9r5CUfjEe+Mp1z3Yw4mE1a2BuuKOxuyS4IhJPkGG61iN9IbHT2lTSoVUkxG+p2oyohGQycLrJ3nA+95yjm2tqcc317QdnB0vGB7d4b3FdKFgaHJuSJBm9w5FXQXASIOV0pzygYKKtVSb01xozFb5/ew4xp7+Cbt6ZyTH/wk8VUia2u4JfDKesH3QsdbruLW2GMmI57d3WXPjzFdknC16pWF0OFqj9SabTSjMXLjAOsnxEvnsbFj3HQ0o8ESHVionrWjay+hb70BG5zHIoIz8OlPfZoffe/b/Og73ySYLPInmNQCqBThGkiaImjEr4dXYWWfwbQkizsNwrmhnTxrFPLvznofzntizk4JpTQFoGmaMoN3oymcNTJlyM54ZRnUzgBd9s7yvh2O21kFjUy+HFJ0hmF07rKSs4UpVac8M6EcMh/lKn0ET4mN2FXSlxYAjzzI6XRJ/n+FZXvk+Ssvf4YnH7hAPZvy9ptvs1otWawszhm8c8yXC9a/eI/pP/4+1Qc3CdLSvHKCXS9xEmmblQqfVw4kELqVnu6u4qhdMg8NN1Yn3FrOaUKgcpb90Zgrsxl7o3P4vNCSOQ9RPTgQuhAIEulCRyeR1oAEzQy0SZEwWOhq6Lyj8WNaW3NSj7nuKm5MRhzWI+Z2QkwKgTYZvFS3QCkIMto51OA0k6G2ILGe06LJE4b0xZOiCzUhhmkxWDoR3rGedTViFhZMpmOapmM8GnF465D9C/tUzmuXizyX+UtyiJE01SNAjMXDNVh85Zjt7+Iw+PPn8c5hQ4vpOryxVKMJbjbjneWCb4aOP1me8DbCaVxTRYNtDTdO1my3AVndxy0sLogC8GnlOGuhcrSzCePnPsb2U49g9neJeFxVE4A2U8r7wUkGY8BqNr2XYvtXlwLr/NRGYHdnm5e+9DXe+sWrHB8fYYxL3CJTDPeG4Sj7IJdx9B5luQyYIt88wHTu4pGc9Zg2QiGR4inlzz0b9pUZzMYoYTqQ0lBljWze49nPyVhQqc8j42l3XkPvTqGafmBzNrLruj78BS3BcV6xaGNUgDEZ2WpU0a7/DN1MzhKqNgZn6HpGZX14scralsB95/agW/Hd730PX1U4o7VZOgQR7ypu3z7Gvv0+jx8cYSSyevsd5Ql4Q2w7YuhwvqKLkXWz4naz5HC94rBZsewaKuvY9hUPz3aZ1jVb44rYqtvaSse6C0VFL6KcnBA6WtGUdyuRVgJtCAQDwQY6Z4m1Z15vc7sac3M048TXHNuKpfM0xhCwBGvLhifJTmTzbKDIqOTT1TmXFkM+ISUt3GFsrzIg+RTTf0/SemnSs7LgO9WIG5Mx09WCybSma06BmtFozOH12+zs7TCa1L3SYj67RTBnegHmBW7TPXddR2gDfnuL5QfXme5tYcYj6HT+1s2KuUT+9sH7/MFEdb+fq0Y8W53n41XFjfWcf//am1x0FQ/WE3wM2BE4V1NV2ufOekdwlulnn2frq59XtcvTFeyOiKsWqprO+uK93HOdltHr/7KRSSN5Tsbxiaef4dlPfY4//me/oxy81I767iB0ziB9OEC9cR9nPJ+8d0wy+Bsb/C7X3cDoYbp+yFzvOu3FaCtfhOXsme/Pf9/ApWyvRCA2Qwb2Q8LSs/fbe9zGKL41DO/K6wrUoPIrNhMWMazXjcIJ97g+oszkztTjhw1gpooYES7ORnz6qSewztMFk3TS1GpGUZnNdRfprGdmDOuwIgbHP7v/61zuDnju5p9yvDxh3q25dnjCSbtmGVomrmKrqnhgusWFyTa1qzESaKQjohXqXdfRtg1SQZuaTRpQgXTRtHkrHR2q9dwZaMcV8/GIo/GIW9WU6/WUA++Zo3ybzJCWrMud6AYxnTZGlCSnUr2mxNcFJB2OFQMAM8vzGtNnJaQPPVziz+jwxWKsxMCxEw5dxSOuhhDY2ppyerxge28X4zzL4zleBFNp6l0YYiOhYMjWVgqwp8UpEqlHIxZHh9SzGbOL51jfuoXxnm7dqCzuVs3UO14e7/Cp3V0+MZ5x1VZUDkLX8qcnR7h6wrZxuNEIWa31uyOIJBBbDFzYY/rso3CyQCYGYsCMa6yxnFYVIdFKindyBuguv2aQqaL3lgYRFaBZtfFkxBe/9GVe+ckPuXXjGtLeGdLkNX23a5hpy5HC3UIppTDoZrwbMH23cOuun4WGp857JISEnylhlrYlNB02lfaUkOwumFEZm7PGRyTx2vTKNWxITzPYtO/ZUHN3g5QmR4CmaxWtE6WcZEzpri7Z4LqnUcoFp3lmh33Py+AlC2hTJfnOyPHrX3yehy6eo2kDsmqICcPR9Hxqw10gDkMbhf/s0f8W/8HTf4M6NPxP/t6/xIM3f8DE1+zUIx6dnGNvNGFiKyKBiNCEjqZbY116wqAdTpvQETDEAI1ol9qQvKK1h1BZ5tWIUzdmWY+5VdXcrsccO8fCVnS2KlmoLmFkNg2kiqRHOnKPrhwyKFUiC8n3rcdiYQZr5iEZKXTcVMso95DrTyAhs91776YsGps6zGB4z1c8P65hvsSPayZdZL1YMZlOaWNgOV8y29vRusSypAQxSuLUc8KlbJHWIKpHBzvn9lnduEXcmTHa32Nx4zbr1ZJHtvf46cENnr9wP1/Yv6AfulgBK2Qypq5H7O9f5Fzt2HeG2fYOI06RrlPjawQ7nrDaGrH7V34D/+CD4K2m5w8XSDXGOkdTp+ZVph+DspaHoYLIxiLXAyiN1WAtFwNlhIcfeZjPfP5lvvGPfosQWkwKm7LcTu/xZNMmyICLlUcz38UwHZ91InVjinbZGe4XuXMP3e3KHkonqvnVxZAkcfvXe+/1sHK96zv8/DyfxbFwqV2UCJLY2GCKkQGoRiPW6/XGuEmKfyXNgaRx3AhXB/ct6ZCOxUPqQ8WzuNXdro/MvpUvy2oA6QtNauqYiV3ZgtYS8O0R1z+4RYwea2t8PUaMQ2IHEhQYjxoK+HZOF1tujC4QsTS2Zufco7y4eo2Rr6kGkEII2nV3TeRoOWdFoJMWI0LtVexeTCRaWBth5Q2N9cxHNdermvm5fd5vO+Z+xNLUNNYRMNiIFlGiyavs6WQ96DzZJetAH9P3uNogDBPBBCkTmstpssZ5FFEeUdIWVuwupU1t4oqInD2igFwUahDjeMV3fGE64WLTgImMtqcsD0+RpmE8m9IYw/zklNnudsK0gBiTML4a0xAa7XGWFptEWK+X2Kri3NXLCNBZRxcCflQzqse0MVKNZ1TO63MlnR7jLL6qebge8cjpAU01we7ssTfagtRrDYmIS+Jp796gefsmVTXCPPEIsrelzRnMoBL9boOQr7yTsl3KniuD3w88/UwKrKuKz37hC/z4h9/jrddfU/wpicBlPCjznBhspmyUMqa1YQxNlutBlSzSITabbbE8nQ9CaN0/zrmNrj93PlpvuPT+kveVMm8F47G59GPzXjQDJiVT17aaqY4ICWUpmGeEouixXK/JeFjxzBPOCZrplIGRPhselnsAvNGKjmzabbrRj4qEPyL7ph1jTQ5FgKquUxW/VfXGBFlof6fIrbXhR298wMcvTZXnMpJUBKmbLXaadjeou7nyHas68m+89h9jEC4s3uVrN/8Ab3SjdmmC1l1DMLDs1qykY2VaWgkYI6yc5dR1zEdjbtczjqqKZVWzqmqWxrK0QmcqgvUwMpotydrixiA2YkS9mTAELfME0LveecCzZxMZ6DgPJigbJO8rlWw5C3hmI5fBxhT62YQ/dV2rdW3OF26KwejMqu/MsRnxPpGLtUfWC7CRrf0tTg/mmNZQj8f41rE6WTCeTMFEDdyitiSKsUNMC2IJpDDPWpx1NPNDDohM9s8zf/dd3QjeIYkA2SxPiZmpG3u5VuMszKbsrxt+JA2HNz5gFsF1DULEhUiDwMWLdD/+GZOPPwbPfYKwt41ZtphZKkmJadNk9Jp+o5LGVpI3okbJlDWaD/G8VcrclDcLF++7zBde/go3rr3HcrEmioa0dxMx2wheRHpZntwgdRDGWJIaavq+4/mpNg0QQVUzBWt0290ttZ+vstEFfO2hDSX0yvcXsn7u4MqGaDQalc8OIeC9V4/YGnxVac1hGovCHcpaZ8OQE1MiHYMltyWHXjWhvHawrvN6d6SSlMF92jP3fPa6N9BtbTrpk1ssmrUidZbob04zK4Jl6g1PPvEMO2ZNFxs66YhdQ+wa2tDShY62WRGTjMLU1izGlksH7/LXv/3vEKO2Rw4kmU0ibWw57dacxo616egsHI5H3KpnzMcjbtVTjkZT1taz7CLRmtTueDCAqAHVM11DyBAiVWVBUpffwWIQ6ft/YRQvypGi6g3346SMdoP3VeGHSHpd4ughIjRtS1XX6RTKrrb2W7eW0gAwtm3SoRK6qKTMnHQw1oKFSixrItfF4nxFaCpMCITYsLUzZXU4h7rG+JraVqwXS7yzUHmcdeXk7sNQIYYWZzyI0K5a2uWa0xu3U2ZGMAjr5ZwYOtZHRzo/kjIt3oGxGO954/gmr15/my9u7bLvJnQddK7FACsH1aUr7P36L8NTj0E9RYj4H7+JeewK0TvEGlxUT/UsDrJ5Kitd0SQvfeOSHLLJwN/J1spQGc8nX/gs3/vun/Dqj36c1rR2ydVarRySada079wDiZyXwmyX9M1Rz8Uovyl7CL3Tlsym6HM5Z7VwHTWiuRh4qKGUlh5W8l4wxUsrWGR+vvzdH4JbuSRNHTKUMPAoi9G2thB4Q9elAzdTIl32Pgqgk783r8u+zXf/vdZoJWuUrmirfZjjm6+Pzr5lA5EXcdAH8MWaaqcRABMDTz34AOcmI0wbadsl3WpO0y41bItdCokkqU8EFmHJzT3w782JTZsyIr173CIsERYW5lue236LN2czbkymzG1FZxw2WnAeA3ROS5P7SU1BU8zCY5uApOrFZBUEyu/vHIwEZJtMdBu4renfQgb2Bp5T27YpFARc7suVjHw5aVN3ltCSexELqWo9sbijCKFZU0WPrSqC1aLdd2JkXVWMk5aNc5ZOAtPtKYvTNTZoqFBNJhA7YtepuqdL4KloNk9xL6cGOhpAjZ1NCoLee5x31BIw7jbj/d2CRRg0WxoS8fSfzg+Zn7/MVx94mEkIqgoZWtYPXmH81GNMqLGXzoMfExYL7K3bxBCwoymqCqpbVIl3d9Z0pVnSTSyJhTxc7BtezjCyMUmADYiB/f1dvvilX+KdN99gcXICJtVzlc9I4ZYWxfQLIf/Nqq+s/5RrQLPGkCkZ02I4k0FEUO83HZkRCJak931ndk7WLS55Bsa6clDZXKRu7uRFgWbochv7/DoLdOv2DrtgbV/NMFz9WidocUJu7INIj6uRQrskBKCmcwB1lC6/ORpM3XTvdX1E9q1DnNZS6fcrazfXV+kN6o3l79mfOtZH79Cu1woyxwQkpoxBE9pk/iF0gaZrOBqvOJ2t2F01EIJ6Ijg6ZzipHNe3dnh9NuNavc3cOoI1OAuTicOJo5k3upBFN1oXo6Y7oxBj159WYVPAqk/Fby7i7I4PcaTsxecszQa4l2dRJNUCZWOlMX9MhsXbKsXjWrhoU/gRxagqogjGRiwuTbqkhWggROq6xqIJBWsVzP+Z87xD5GO+QkLEVTWESNe0jCdjlosloWmpxjWucvha6+dEck1TRLo0XsZhbSqANiAStAeYha5pIMIsCG3X8d61Dzhfj7HG4qoaNxoxHo9wO9tcDWsqLwRfMZpM6CTSbe2y/ytfp7rvfmQ6ojs4xPzh96B2yCefxN48RCYOlzhUwVhSPw6GwPaQr2Oh197Ki/Hshh78PW9egVT/Jzz77HP86OlP8Z1v/aHKmSQPySbMJzdj3QTNE1grwtZsgsEwny/LQZQbtmb8NV/WaomNdsrRTwwpHCz8IXWDBmA65d9zeJS7QWfPQ+7y3CbttyGmBmrEs7Jlfl1MPLW78afqcc1qvSY3fS1GM3lMMe19JWAahUXSPUwmE05PT8smiWhXpD9b+JbKRiD3W6MYoyyCZQbkM5zllbffh0XDzGpBb3SWyXiCr2rEQmgCbbumadY06zWL1Zw2LDl9YMyluqK6FViMJphLF3hjHXmvqjn2lgZDZyxGBXQIEaz3hDYi1mKd1/KWzPPJrnEJVdgY7MIBSb69HximmDqDZjngPBb5PXWtE6X1Y+imiZkWkITijcrAOudYtTkmV52kuq5p1mv16NIuUZBVw4QYdWyLuyhgrE/rOJ306VRaG8vNuuJjtceuGrqg3Cw3qlidLJmMJqyahtVyjWutdgCpHN75JDHrtR+Z5K1kMEaIXVR0RIBON46vRrhKl0y1tcN0a4+6rqmqihg6YtNwfHLIz29fI4bAxO2w9JZqe8Ls2WdwTz5GePsG/N5rRGvxL3wMu7+NHBzDYqWemk0eptOjSc5sknxteD99YKb0DHrHKQ9hYWvT/12NyozPf+krvPLqjzg+OFBDl3GeUkpozoQcvTe1XK7IsLxLvyvhkLCxydXISTFIJr0+413D5gNBlOOUC2DIYdIA1yyuS3oWOTNGeT33B2uP/Zw1QMM/c2/EIMKq7ZCgay2kEXT0nCgFvqMWZsdU7ZA6Mp/O5wUMF8kQiuA/QoHy3tk306GnlUvhjaHpOs0EpBhUb1crz72xvHPScbjsuLQdOO87xi6C2cHFEYKhadbM58esVivWzQpocd5xOt3h1XM184kC0sZXrE1OEGTymEn6yipxEkKkWbeIOJqmxRh1WbOn41JPsByDD93YYpis4kO1r2mSLng04K0vr8teVc42mqhi7yFvgKRnLYmhnTM1IQZtrZNE8bLH1bXqVgdIxiwkFqziXqHrMLmDTFqchgSah06zPFEXcTBw0nTaIMB59QwRrLdU44rjwxNms20mW1NWiwXNeo3tPJ0Dm1pImeRhGmfxVt19X7nEk1K9IZvwhmDTeMSIWS5YnRyqXAwRXzt+hvDDvV1e2LrAY5cvUa8F2jWrH/+C7v1Dxvv78MVn8Pu72C4Sd3YwbatLLW1IDWds8jhz1uvulyTvNGMzOsHqQZUso5CVcNP8U1QiQXj840/yyRc+wx/9099WuoQkyWZ6A1DgkAzmppsVSd6X9CTjoZc9/Hu+ueHPDvV68iGTL5vW+115QOU5em+nZBgHXv5wjPKfd6MhnOVK9e3qBWljPqqATH3ug2qT54h+T9nBuJX5kwyaKz/wXte9PaXoEQmq8KANbPU0sKrXbI0kxrBOlKL4kdNmwvyg4Zp3XN4JzICwOmGxnNO0Cng3baOhkB1ztNzioK1ZyghM0lyJHblNsIloNX0BAJWOsF4GYtCTPdXWUlVVcStF1E03G4uizxoYq3QAEDq6QWhg+mLDdDnvadd6zyEEjYtF1IMyiZ9iEs4QVa9HxBDMECfQ2YmRVDgci6FSz1exC2edth63ZmBAo2bkykkc1dsQw041xjUdeAfrgIkkti1s702ZnxzjGsd4PMJarx5Z9nlDJDRrYquaVxGDc75kAU0KlHwS7m9T0fLq5BbLyRTjPaauqdwYv7NDLVDFU9omsl4uictIc2GbyYvPMX72SezxEvPDd2H1KmyPsR97ALl6GanG6ZBLZLu0kPNWKGvybmFGntf0w8A2lWLdArJC/+yivxqPKr7w8lf4+U9f4YN338CI5oqHZNazHkX+uzGpu7DcaTT616YbKC/ZNFTDz86/L97EECY4YzyG4zFc1xuvz17imT0w/JyzJMgoCiDZtO6yDLWC9CYJ9vXfNwT7EyROTFI8/cEupcPR3cZqeH2EdElqr0MSxiK17SamanQHMVekUyYRE5BoOW2F1W3h4r5nSstivWTRtjTGctrtMG/HNJ1q/ESx5ca70Lt4xliiSt7dkVGQmCZNLYHiIRnXASQEqozGwsbEGGtSilvpACVrlifJqNEglRi0q/XA2OlKt0lD6gxwkZQQU5BgEg6lH66xuQgh6BFucpm16XeNtaTMTH/6CFLEvfLVxYiPhnGdDKm1mvKX1GyzC+AMO/s7tOuWxWpBVdXahqoLqoHkK6bT7RSaq+RL6LQkQqlTESHSGilqoGkFpEJUo/38gqU9WvLB/Drz9QmXxjvY7W3cs09w/i98FQ5OMD/+BebhK8iXn8E4h43pULt2gFQ2dZEdGBqDJhTs3cMMoFQSZCl5Bl6TKR80nKMe5ynYSIw89NCjvPj5L/CP/+77rNctsRsGiEMvK60nYxAi0SQsJdU/9gDX0GD0v7vTcyKJGCpAHq0aZJvhhzOGKGNA/XLLYR1pLSU1WKtESV17auw1ZM33u2GlyxDlcNmlMY9C0hnPHhPKdYOB968TEEVpLSbti7xPFGyviN0alws773H9C0iXUHR1cwhnUjPJiCE3vzLlsdJNGouVQLAV331zzqWpIO2Ek27GKoxow5iQRMUtEWcUJxLR7znLSTk7EaTht8YQYiiDkxeiNYZotTuns47hiaKDCNLFct8lJZvUD5AM3mckIk2j+vBFDMtaQykvS/emIGns35WMrSEffOk0kuFnD1xgpOBZG0aYxAmyA7fdBdYtCacwuMpjOnVrra8QkmJgbdmqtmjXHd26pbKWQGDZNqyaNYhSGsajMePZVJnyuTaqjT1+EQPbownHbcsVvIrzOY+xFS4a7qfif3P+MZ7c3WWCI1y7zvr3v0V19TLu8avI/g7GOqT2xHWj/JutCThLOD7F7cwQ14+HDNzVs57FXderDIiXA5zl7FtislxiUA6RdXzms1/kxz/8Lm/8/OeQqhdkYMQG39J7a8YmI5JIrQg5U3enV9XP2+Y9S7kn631KjGg501nvZ9hb8azXqH+qsem6rhhpbR3el3iU8rHYv9daSxdj6Q4UsoeJIcQMfZzFpwbzkT14wHqHdxXNeo10sVRGmDRCd/PYhtdHGKW80RN2lIxPlEzV0Mm2WYpjw62OSHR0CCGO+cVRxDJOnhVIIj5itMBVmwrElGbdvHFjTAnPNrwl74q85u7eHifHx0gXtMuod9jKq/xK4k7UdV2YrpDc8hJW5ZN1QCeQzXABFICOmR0NKcMX0+FptKzAqJeUeRvGmFQf19+7TaGKiNA1AW8N3tuNBTcshE7fdsfC7ozjp6Hlc1Y7oKjLnkJL41L5D8RgQALjymMnYz0KurRpo4LaMUbW6wVNu0Ki4McTLApsVtbhK22pfXl1wlFo2b54QQ+SCCZEnPU8v/84YgOyWjH3lunzn2L0/NNYp8RZ1waIa2SxQEYjzLldjLGEd69hnfZwsz6357ozZNpYnXczUiZ5ox9xDTNWgsFK4PLFS3z2i1/mvbffYR2WZU7v9G5k8EfiChnIagHKzh8cHIPw6izojPT4ZJk32fSS73YPZ8ekNxJS1nEaEMSkSRKDS2S7GGXjPoKo1zoMfXPnj3zPRTxQEo0E7rgnkajrp4WqqtUxaDpNiuVowNxbpfsjjJIkL8huahkbUzZsdOoxCBQ+TXEOC/6hDxERnE3ZukRmNMnYhTIc/UIcEsFyZJh5QjFGnDWMas9qvaZtGs24paJSo35n4XKISM+MTuFm3AD90qQafa1Pm3notpeFQcqUYQih03e6XjVA7y2pE2QDSjr5Mgkvf3hejIPQY7jgzqZo85/l90F4z0TmUTgnid8UgmoXicVUlbbktl7jwq5VsNtX1NVENXw61dS20kBroIuEEIlt0G4hVgBHWLesliesTk9oJHD43rs44/G+Un4UwurkNqEy2E89y+zRx6gri3n1DZhNsZMZ+BGyfw47rpFkfOJb72Dqsb5mvoZqtskKGoz93a6saFjwpMGfpPAjb9eShctRWP69VQLpC89/mu99+1v89IffQzlbuqZyKK5esRSiqy2bMqXGgcysNSbL/ujTnO3DNlh1+noJxC5s6BYVlrrRVlwhRuXlKW+8LCF9jS17zVaaBaMLxeM0Egkhub8ory2K8p1sHIRnpJDNUBJaeT8OezRicvg4DHU1EWQcdKHV5/OkGDWjHX8GT6kL3R2hT94QzjmwGqq067V6HKG30jGHsiROjIAERXgVI9CYJ6sE5pHNolPee/b397l161bJpBRuBeppVNYyqWva9ZrlYjGYwFz+0Lu6d27sDKIPFmyq8LfJ6Drvi+TEMLuRU7sl1CTF+dm4pO+xop9jrVMlzlRLl7M+kia1qqoEhm9S9zNeMOx8cYfBStXXEIiJAyYiSKcE1diqgbagZETncAa6tmHRtBhrmdRjnPdU9ZZm2oIgqercZHazCDFhTb6qlShqlXzZho4mQu0rZDJi/MSjnPvqFzEXL0I91rluOuKygZOFerB2D9t1yPEpbO9ga084XuJmY0zTwfjua3LzVM67MZ/s/euGztJZJnEf3vW/y1DH7v4uL738Vd56/RfMTxa4yhBjq4diTN4Cm4alhy3yPW7ccdnQw7nbKC8xOcWeQG7vabouJT7yuWXwdUVYr9McU8pdSK/JYyJGiCFqMiW1DBpGH2oYRP8tHa4qECnl8MxJmPKMKdwrz2E2owh9xhwtlScnBs2C2/Rcq2bVN6f9kOvetW/SJZ5Eb5iGkxFDUGsMSIyEEKiqSifQ9A+ZO2iSQrOi8WP61sT5YbMR6LqOmzdvpofT8CdK1BIJ1Ch1beTocE5VjwkSktvcL5K7aUHle7fW4EK/KgOyEX5GgXXXpnZQdwdas2RsxtQy49sMFp13Ther6CIok5jP7cECA7njns+GcENDBfq+Ywy3nWO7M/jKgFUiZbtscKOReqmp/i4QUsir5SoSAvPTY8DgnNIXXDT40Rg/HTEaTbG20oPIOMRE/OktOgvT3d2k/gDWW52Tq5fY++yn4GRBPH4L0wpSW3AGuzXDXDgP0y3sqsWsVoQLOzjjCbePcOd2ieNaoYDiPgwOrGFIn2Y5Z9xy19icjlY8iP6/FNVmbEzNeJn+jfF95rnn+fjTz/Hdb/1zYuhAooL+OTzmzkMul6X060MPvoF80R3fU+6zfFby6vOaS7en+K2wXGmxrAqaGoy3OlBd38W2fGYISFBqiPZnU3V9rcGzCdBOPRuN0fpPY5JmllJNDBran+0rt2GsBt+rB7Mohun6aKquKtqupWkavHWlNduHXfc0SlXlyiTmRWKEpFBo+oc1ujmcrUoYJ4leTt54RtOmxpjibg9dwhLP2j4cdMljsSho3SW2aAlxjAKRXdeWWDcvnKGhuxvgGBOqLuRYnjSIes9i82t1Qetnpc/Ip2sq4hQLiUCFAF3iLTlRrhIou3XdrJMKn0lJAlSW1mQCYBLGGniE+QTEJqmKfBpKv7mOvOONaHiorlUgzTp8wtua5Zq6qnB1jUhEujalbweSGj7dezTq0kehWx1iTg3NaIyvRviqSg0rK7ZcxcFqRXSVNk4wRhOx3nHu+adgOujjVnmYTmF7mzgea8HuzdtaqX7xPs3GdC1m1epGE5JiQw7Z7x6yZWOV65NzcLZhAcyZPz/kowZBHCLCbDrhq1//ZV7/+U85PrhJCCat6f4gIY9d+b4MMqc1X9ZbWXn99yRDcPYAyleM6plq+ZEUsF/Dxd4weuPpiL3Bzf9mTGFYxzYbHiVi5oYIDl3vtkAIqbzJ5vydBnN2w/iketcBJFIMYdo8xli0Yis5MGJoV4l2aSxtCAVM/7Dr3piSQJt6pdnKl7ApE9JEpABY2UsZ4i76ESVhmjY61OMRy+UysUY17LEuNwQc8ItML/OJ4Q6vZzqZIiKs132/NPW2coq09+6yUcnqipkzkfEFShg5OBF6BEKNZ0htmYdMWkzBjTQ+N2RUrU/XGtbrtS5CTBkfVc7VDW2KcRbFKYREklR8p6or1fOGwrgFxcVMFF6x8OW9XeLb1zCxo7Xg6zET61nO59imYTSdUPtKyZzZa7NePYGk2a33HBRTSKO67tasmxVWi8zZlci358csTw+ZjMZ461lZw/STz1KdO4dMZ5itLdjdQaYTfbblHPPWe8hqgdndxly6AKtF0vgBs7dFOn4wCFWqAwsbwraDpZkOgJz6PxvaZg9pGLLkP83g5wQClfclHjkfe/xxPv2ZL/C7v/2PsLSEuPm6fA/5e5W4Gu+IJiAk3sLm2j2Lj+WMav73fGhjeofADZ4V0OaaxuArj5FUZ5k4ZV35DqWdSAkKeozWZUOUDzr6A7Kc1WmtF03+Mx5exmfzaskNZTWk7vG2fvTsmVG88/qIZpQpXCg33MfFfQ0YeFEKeSdnsgsmd0hI05N+F4OCayGqtq/1vRynxSC2P0lyD3b1oGIxMMakrimFi9G703k9nJ38bJCKsYKN9T4caAN468rCDtlFTgSN8h30i9Mlo2lFgUJfV6mzRPJMipEkKVRK2lRJxB4p4aI1KR0ekzE2SejLunIQZBDVWOEdMRxWjktbU+JiTrNY0i5abO2ppmO8dQVkDzEgQU/hsF5iYlCNI1+n2F8pDc57rKvwUyXLeeMI0uEbFQFbLbUriBk7dr74Alufeg4uXCBOaqRt6W7eIL57HXntdarrtzBXL2EefQRpWszpArl6UUXdqhGcniDTGqHGI7jYh193miQKBpSxoQ2DZOhN2eADeg/3Qz40/Zsg+KripS99hVd+8mPefedNREqd/oYxyn9XbaTe09bXxWIAdO9uGs685nImtvgoZd9pg1CBVOR7BkpIz9TGoITFRMiVtiEbHzUKaZ2g9Jm7dijJ95Pq4Eh7IMs6kzyygB6aw/vXe+kdkfx5+ugGa4UYA95X+MqzbvtOK3e7PqJxgEosjEcT1usGSF1xTXLtUMuoBZymf5iBNQ0hZ8KMeltRiE2rm9a7UptWqu7TcxUuRXpgSw8y54lsu67XPrb63blMIsbIarVKPbCqNNnq3sekQ5OkyZLRzIWJ+eHPcKPS/zdJTqMc0wIun04hpNDIpE1jyiIvs2TU+8oYRHaRjRiIofBsspfiUyV/DjOH7HFbMnwQI0RvMWOPszXT2kMUunVHt1jQJUyobdcEDPVkzHhnGxNgfbqgMxHrYTrZYlSPiV2Hr2qs8zhf6b0HVWBo1kuMtexcOs+sniDG4w5OOP3df465eUR7coJp1tCuqS1UokqZ8b0bxIMT6k8/T/XALmbVwZtvEd+/jjiP/fzzxHPbhLrGKj2TofXYBPn7mdFpHW5YU7A+9QBJLGLZIFnmec5rQ5KXnL/l6v1X+dznv8hvXbsGcZnkj/U7z0ICumb7DFxMok7WOOXROcN0MmO5WvRre3DP+fvzMxuT7jkmIqXtt3zWcdIEkCBB5Xo0lh2W8ub7ywiF3IEPnX2ObLBiCNR1rbWbqzUZGFcjGzenxvQOZ8GbRbQyoYgXamcgBg7Eh133zr41XRIZU4OUJy3aRIOPyv5VEDRVLdt+gRhjikZRTMdW5Z22/9GhxwL1eFzCG+hTpyH0AF6eyKHY2sYg6kjQxa58f1VVWnRaJl4zbtkAGkxRAAQFpXPhrLAJOueJ1RnoG13m8W3WTa/Ol8ifbdsmIKAn9NlK7yc0fVPBLJ+ScboYsyLh4LQTKVK1UZSFPBmNtYU0hinCzFlM6tjSrJcggvcVk9FICYtYfKyIIRLajtNb1xX89I5xPcJax2J5yuHxTWgDttJnH/ua2nlqV1P5EaFr9CA5aWhkrYqiH7yHH9U4XzHZ3qI9v4tsz5DxhIVz+MceonrmY1QXLmCPV4RXfoaMJ5hLe1Dfj71yETObYA/mcGlKwbzy4t+IudIGoDdOQ+B1+MJMmNeWVhR8M83khsdUDoPstTvHZz/3eX7w/W/z+qs/S3SAO+VUNo1LXo8pDBq0ul4sFgxFP86CxWe9vWxglSVNUneQYgTygZ2bS+h+Son9DU/w7nSKIWA9BKvzPuu6jrZLOkgoppY/xaQQrwx3WqOQYIcEQWj0kB0HbbEl7s9glLQkQQG8YVgmQik7EWu0qNP2ZSImAW0ZtI0ZQY7Sy7IKSVI3FkJjCYOSUcp9ue42gcUiZ2/G9J5Qvqy1hdshaOW1z9yn9JoudMlu9ItrI8tTTrDh71Q6ZKjhrN8TVJ4iGekYQqnhKiJhXbehg9M/TzZ8tgiNDV9jE1Uii2kBrNdqkIyB8xGmodPDAU81GtOtV4h0LNcxhcdOi3Ctw1cWV83wSQWx61rWzRxnarZGM/xWjfEQgtAsVxwvF3TdbUw0zNsWCYGjW9e4NNliOtlK8iUTQlUh+/tMHriI/diDmCcfw27tqGE+mhO++1Pk1k3MIw8i913ETKdwpdaEyfEpbmebIil3NsQyOTA66xmdXR+bB7mgekXFsuU1Yja/YBAU6T1E4fyFC3zxS1/j/XfeYTE/pXeeN7lThcqRSJ8m17+kWk6LBRM31u7Gdw+9JVGvSyTV1Rmo6zHtWnk/dxOCM9hSWjQsy9F1NVDGtJteXv7u8lRnjKyYnIRJl+0t4kYGMf1zFPVG88GstZbaslvQw/RuBnJ43btxAAmHGPzOGJOE1tVj0vDL9M62MeVPIKW6M0aj0gUxudE2qlUPnRIQs1fSpmp9ci3UEKdKg1BIiamCfigNOhysLIKew6A2EQtFRKVv0R50Jm72Zi/PmsiYDDaDLuzU4UQ0S1LVFetWs202EUOH7m1ME6oA9iD7UAa3D0OG8qFlcZHuJeoZ3AMluk7OCUyw4CqcF1w9xlnt9mIAYyG0gdg2YMAZR1WNsFikDSCRut5RTYjKcjo/4WRxzKiqmU222N3ZZzyeYquaSOSV137A/IXn2PrE8/hWF1qc1Lj7L+AeeQAunINxhQRBbh0gr7yG+aMfafHkyy9gH30EJmNwDlmsiO9fw29PiU7rEUMWtrdnxmmwn/Om2RzHTadKYLMWdnANV3YfNlMUQ/W9lmc++Wm+/a1v8coPv6Oba7O6t/+MvKGtwZoItidPmhTfGDMM1RJaU9Z1NpoDDzAlh9qmSWvAkDE0ZyCGiHO6jTPXKDsO+pn53soK7j1+NqMQ4ENDS3KInA0Sm2FkyWKnUTUoLymHbM5XTKdTjo+Os0rWh14fXWaSXL9MeLpD00UkqVImbRVJHhIDL0YospogqZtualudHVrJmTDTi1ANcKr+VFIjp+o/G/t+o2A1GxdL6pGVVPiAPrMh6eSIeSGol5bblKtj0xVj6VNdUij96yigqmJbSjOwKa6IeQbRVO7wLI4I1qoxzEW/NnOVEGJSMBie9iY/19BAphO5toa4bkqZS5SY4hUHdKmwyuFG01ThLSpDYx3j6Zhdv42vay09sZ56vMt0vMNyfsL89m0WXUNtPc56xn6EWTUcf/tPOfz5G5hqDJMxcTbBTKeY8Qyzu4utRjiESRupH70f82svI3s7yO42sfLI6SnmjXfhJ69h77+CPP04JkSisaycv8NTuisOQg+xKk9Qx9CcsRs5J5pNVthY5YPVnjdzDlkksre7zZe/9nXeeePnHB8dbSgw3s1b6zFE9cyz3HL2iK01dF0s8EbWyM4SOOnkSml7kywTumpS+Jglqk3iRFhjEht8eOglSowt1XhnnngzhLvrlaOHFP5mAmWOhozRzHnTtWmMjWbootCGBlspZtw1LV043biLD7vurTw5jIYGRmNwv3qzbafsZ6NxeEj/mCU7Ygi0oYO6Lt6Cs4YupGyaV1apiBIwMwlTjCkpyCKTYE2pVM8LZ8jcvnNMdRCHDR9Ncs0tKNvZ9uFcBsjze/rPhqZtiZLaWys8VTCpNtH5vVGAOXflzYW7ukmSgUUXbpRIXVXETttPOWcJIQ6hqo3nAPA+aS2HXDipPurcBIJY6sTAjkloyxqLEVfi+RgEjMXaACFAG1guj1lFwTsVcqtHE3xVsbezz4X9C3ShI3SR9WJJXM9pupZuCb4zuGCpaottAvHcBHP1CvH8HnLfJfzVK4z29vCTCSGuCTcOad94E/Pme5ibN/CrFvv8M5iPP0ncm6jIm3N0VU3nakISDvtQrhKbmFMsPyfjkDW+US+iOAjZlg9+zmZ/0Ig6/btgEJ586hM888kX+OM/+N3kqZ8JrYuHonNfVxUxQOxi8hT6tZS7mAzDHv0uUzhJ1mZCKMkwgHGeGFTwP3vpmx58TqzomBXp5nRPxdMiQwVmwzPSWxjub6E/AtnMyqXXGufUIxJVmDBQyJ0xYckqvJeeO3/5Pa6PMErpoc9moYwKgqsmscF5BybddNFhoXf5nBodrb5PqU3UW/jE009ydHLC++9dKwakfA8MwDVDIUih6oq5vCPfE/nPwSl5NhwDQz0asV6t0hdsTm52t0WyIcxhVeor77TVs8XpYIeQ5FJTFjF/VDbK5AVu8swCmuIFpUdI0tYWyVyQ9M4kOJb3mXW2iM2pfnUml8KiC3TG4IkQ1WU2sa8RlNjXX8VEfo1iwFd4X2GjILGhaZe0q1MqUVG3qqqpRw7va0bbE9wnP4598TlG/8l/CBfvw+xeQd6/jpzMiTduE9sW/8FNzOvv4cIP8NEQ2hXdckGzM4XxFHNpl+qzz+MfvYqZ7MBoAjOV8bXWsa5rulwwZXrW/92u4likabdpvDIgnC2RJK5OTz2hx29M/1mFNlC+Qb2cyWTMF7/8FV756Q+5feNGCVV0/aT3DA7GGLQrczQ6n7nEQmVlpWgKlSYUkiFwpceICSWUjDEHROlZ0joTMUwmY5qmJSZuXjbDgkIbNsSyxo3LMEj/OWeNUD6IfdFv19fl5hVmMDg5um66VjsfDbx4DTMDptNJqKpK6TthWHlx9+veekrZC00Fgr3ErCl6wQKIS4WL+X6zZU9OshhHPa779D1qmGaTEc89+xT/+Le/AZiSXSpAdB68JHjmrNNq8xgJkg0OyezTG5jE7S/OSRrEPODNcnVXjCEP5hB011BAU+/5Z+e9qkPmDQBEwkDMLRdM9uGF4qxpnLQQTU9co0ZVDWBMcizp5A0py5fD3BhoY0SJeLp4nYVJiLxQzZjESLRtYjkLMTZYEbq204FwCqIba3WRob5BajiBdSOqsddShK5DusB6vaRbRbw1VNbT3LxB9f2fwvVbjM/dz979j8AnP0UYe8RZNYjrNd3BAnP7mOXJHN9EajulunA/PH4VHr+Cf+AqZjrSUGOtBF2cBeNZVTWdieSiteGpXhZ8mas0b2kZZAy00Ej6hbQRvAxF5PJmT2Y+/U76ED298+FHH+fFz32Bb/zDv09su0QUzOBxfwBWvqLtmqLVLRJZrxvE2IHWliF3NileWczdQyi6Rv1BbdTron9maw1NyuJmbz9njsm1bIakc6Tv0ffm5hQDyR+Tz3XZgCustazX68LsLoYq3bM2+shh5ODwiKF4nQaLdKn20yb6zj2uewPd6eTG6CD5VHbinE2WOQ2EzsiZBZMMWHpv6XGVQT1jWTYd/8V/+V+XI8pYi68rVutVKkmB6XSsoZwIp6dzQqd1SMZpTJuVCAzpO0QGWkWbnpKIpJ5qXfk3EUmCZy55RDqM+QApfe+MoU10gSFQlxOL2TjKIBRQzCCU00v5SLJR7JtfW+4nqUxgBmMJSVA/b5Mufb5QR+EpW/GpFmLTQUgbxRjMaAQhYFpo2o7YNmqgnaXy2spbbEREjaZLOE40hmo61ZAnTCF0hPWSVdMSQ8tyOWcrRN778Xe4+rOfU5mKka+w1Qy3vUe1u0W1u4dc3Kd6+nHk/ouEC7v4rS3wBrNaE5cLzKTW5/vgQA+eyxeIM8e68mSi4pCwe1YhsQ998qsp2ExxqstEJQOX3yPlV6XWroirJY9a/y+7/DCqPJ/7wsv86Ac/4P23f4FEk+Rz1aOtqqqE/W2bE/TZ2zDFi8tcIhlsbg3dklpGlIRB2qRwSlmDZ3Gs3lDnhIw+uFKWUuW/6b2ncnqb3oMCGI9HNE1TooOYalmH18ZegoIFZzgkOwLk8SuzE0AstXPYqmKxXHCv694FuQMNoww2W0hqjRpXjydjBYVjllFIaUQZsCaMLYZA/adY4l1jVf+7Sy5gXEWcmGRVlXAVQqdZuwGj26ZNnWPUGBUyj1HSaZTd9J5TktsY53HrwfMe4NQmjTqYxoBztWYQ0sowaBeWKKjnmNjW2ZjZ9N0ZTA+F62QS8ZS8xvPgDkKFvBGTMfKO3CSzT+epU58XcmfhKeuZLFq6+ZwYWyS2WCOYFoyrmNYjqmpMs16ljgtO+3pJVPeeRIyzXjtgVA6JajhdXWPNCBmN6KKwFkGc5fLxmFcOrlM/+BR2UhG2J9jJGMZTZHsP14HMl8TX3qP9xbvIekV7bsrkiy8QHr4fe7QgvvoW8sEBZjrGPfEocbGC7V2yiIaQd3EaHdkcqUhvgKRsCAbjxGATSQnxBEprpihRJWyg4FFSvnv4GbpOrly9n8+//BV+6zffopNUrBssQ2UKpbjofQj06pkZW8wHvWho1wPdA1pK0v6OJnf27ekH2XvLa2X4Z7lySJgZM1b3YkzS0brsexb2apUy3qhRdc7RtUl6ZHhfxWPNn2NK4a1BD8PeUKaxMwJiaduAtO3GnrzbdW9GN73lU9w21UgZA8bijCmkQT2Zkr62z7iQPkyVSIkxarWZMSZ139V4PYTsWaTRzIsnCk3TEUIsiH8B59JguqTQaI16bs5C0vDUZ5D+5DNGs2n9QOmgafycB5DeaEgqyUAxAuOTc5/cflzOikiRI8k3r0XHkRg7nKtwTjMuuXtKlFSWsBFepGWVvMxMQLM2i+if3ZhgorBu16ybU8zqpCgyzNcrjhdz1jGw62bs+gl1XeNHI5z1TO0YYw0tWkBp0NM5dgEThGgs3tbY2RbmvvN0F/aor1xhcu481e6U63/we/jf/QYX/gf/mno+p6dw8zbtrQPiuzdomg4zGeH29xldvkDcGVF/cJPw//0dHBAu7eNefBbz6aeR2RhOl5iRh1Rd3vuPcsdzqwfan/v5sMgZ1eK6Dj0liuo22TRpJGPIQFI+VGHgLZ0xjJV3fPozn+UH3/sWP3vlhxAT9iKmANhFc4gc1rGRPieFdTaTHrNRjIPQRhIbQmJRGtigxSTJZpsOR5VWBj2wcvdni3GKSUXpg9NUdJAMfz+meQwzGJ9Dh2EYWTSVMPiYmgCI3nv6oDNFxjoPipmmKOfP0s0ku79Z5Ek3Y57QqHK2yf+0Bm3bYwythA3wb7lclg6d2bCMx2PWbaNkvzOAmzF9v/RhkSPopDrnaZtGjVoXyiRn4qZLnTiyqFuUMr5qzbO7Mqi+zhMD4KwaV02BBgUn0zgGUemIKhVgWme08j/ZM85snuzSm8TKJcX7+XFzMmEjnVxcfjDi6L3onoke03zEtsUbrxuu7EPL1tYu5y5d1bFtAy4YbOpK07Ut0aZ6w/Wctm1TR9TAxNX4esJkNMZaw2S2BY88rOnpkwXtrSPc8QK+9324fgv+1t8mRs2shsfuY/Tpp5BLl6mjEI9P4LTFGi0nivdfxVy9DA+fxzz5AFLNCKdz3LvvI6sGc+UCIee6+1FksDTokxJy5neDE53h6+nnZmN6kjea+UmSQ7+zmGL/+vz78+fP8/mXv8Jbb77BcjGnKx9siipEvp+NkCt75MalNa77aKgTluO5occ8BIZzKp4QlR2tCzp15M1rqE80ldhP31wMj6oGJMkeSykCz/cSYyzcQ5u+9+xeNMbgEwksDkK74ZVfq40sBqKN97g+onEAJaVdVCSNMBqPWDdNcjtNcQNNOaGS4UqTYVOXzrxgrEDXqtxIlJ5bNEzBDydho3stqbdaEpDO/A81yPq+IJGuTSAeKdu2Tlo0AwPbhaBSvja73/mzhIwMFmA6f7/JC1uxNaPuF8a54vX0xrdn33altMaWsXLe9aUoZBavlMJefUM2xlIObdtvsdRny+DqEYymnB4eY0JkvDsmtkJzcspqccR6sVDj7B3jaszIeabVmNqPGE22cVWFG9VEZzEnK3wLIxz22jHm2rcxTgiVwT/6EDx4H3ziMbj5NvLic9jL+8Sr56gy2Fp57GyM2Z9pv7p1S1w1cLRGtia4yRi5dkr8+c/g3WvwSy8iD02Q2qCcnjOhyJlrKKhXNu8Zg5QPz7OGKjvjQt4cunul/OPddsHgp+SBPfvcC3zvqW/zo+98EyOqQZQ/vHht6RquuWycQpaDHhgPkwT+S6QgUuxJ7+Ol9SoppFM3LKFX6bUiMMDiMhKZjW9+TaBsVTLAVlZWMTKDrKX0pOXsVZbgZiO02wz58nUWo/qw655GaZjSNuV3lq5pk+ytTfG8pvfXYbP6d3hjmRBpBGazKQeHh+BdqQvSm06xqoHcyjrjMfmBSxM8ZzY0hfOkRYmY6FLcqnfftm1x83US+gWb3cuYsImYJvSsRdeWSTnDmOVR+s/xWZEyGciYtJ5MqgDN2ZaMKWh5TUxRZu/lGSS57A6sVV6RNaVJghlwoCKCdYZlUGkZN55w4eoUE9R1Xy2XzFfHtKsVtZ9ArW24985dJLRLmpuHBLci+Apra7x3VDu71DtbGAeyfx/yyafgg9uEa7ext4/hvSPYmbF3/gLtyLP67CeYVmNMs8Z0K2S9RpoODgWO5kjbIrcXyGNXMDs78PAFumUD797Gjmp4+Vmki9rkIOqJG4pRPrv6BmtLUvrfZOeiDx80aywbb9W/ptpHNln16kX3RuNup3nZ4GkN7G3v8PKXvso7b/6Ck6MDVqtAJLXSzq+NA6PSWwNwYIxoyOMGEtLSY5v6xpRts0nIP9FpnLWF0pCLybWURde32Iy42dKVJMSIFdEuOQk2KZGF9Mkb5xMFIeawjR7/zeFGGm9JXntG4civOTteZ5yOj7ru7SkNXdkUt4oYQsg2NafLBx84kJAtNzmITQGOT0+U2zTAifJrM+Zz9qFynBoynmRzCjd5DqICaSGGZCT70yb3rNLsnL4/oHF50XdOQKQenoIo50BJkihw35+sumhyuUz+DrU/ZoBV6EaQIqOYgqvUCipreWcZGJJbbdKCsJIaFcSAs/0BAWp0XOWRpuWIhugtTlradZtYr1DVIy7e/wAYSyWOUw/feO01fm1nl0fPP0X7ZCAcLmiPjgjNUnWdDJh1A8Egh2/S3biJvf8+7BNXMfe/ACdr5JW3ubg6YXH7gKN332X6wENqIIKoWNvRIbz2HuFwjnngIv6Bq3Q7+1jTIX/0Pczjj8AT98G5Ha3zQ02swSLGZTlnistwx7rUgeg5RT1tIP98NuzLH1d8ozP/+FE/b/wurYMnn3qKp55+jm/94e/irKgRSlGDIOX7hptZUQM9WPRwyZ1FXPKghyGmeu8mai1lbpKhWKP0MEhK2Wfto0yDyOvfYTTUS6VYkSRBYhLgL4MoI4iGi8OuMClBFAd7OB/wxqCJPOnnYAjTfFSodrfrI6VL1MoGZdtmzkzyjPJND61hdtHyTeVBLJ8J2LqCBL71Kclx6VBbvhspFf3Za9LvSy6i1Rbacd32JEpR/oUkLpXNHorVdtlFEM6QMhxJ0jYmB3rIE0lLWN1vpUEwfCZjiImnMSy/Ge6loSHLnlVMBjR7TP3rkoEta19D0Hz6GpMqsKPKnMaontn7Arfbjt35UXq913GIbd+Dazrln9+4xd8m8FQz5yoNo3oLc98M2dmhbZeYTue5mzrcpz+Bqaa44xXx9JD42tvEn7+Je/ETmL/6Zczb1+APfxPzJ68Sf3RDT+ZEGYkVmJ1t7NNPEi+dQ15/B/v730FuHWOefQSxYH72LuahDrm4D6dLiBFzcV/P3OIgFbdhc13SwyQbVQeDf4dsHM7+/iOuDMZ8uJOWvLHIZDLmpS9/jVd/8kNuXb+uHYRDMrBJQbUYkbxBBbLaYQn5jCQ1kLPYap/VNRitdcveenpr0zblvrPHl4XqJP8+QRRlXETJu5lCI1luR4RcmmJMInamW+5C2Bg/ExMdkITZpmjGu0r16KUHyMsT5XH4iJn4yL5vAOKcZn9ESvrPFm+0H0hJ4FgGtYE+/jWp46rRshMdjB7RzxyJqqpKgS7OJob4naJUErRi3mLoJIHSIZdWqLl0G2GasF6v9H6txaVFH41qG9q00ss2yCeeJJVGQon9taGknmKeZFywSARr+xMK0ppL7yv3HkXJls5gvSOk/nNZn6o/bdK9GOgXi0m1a6q9FK2wiIY2RKLkshzBVgqmZq5MQPjRyTE33Igbq5ajmzepw20F7Ue1el1YogcXoH3jPSZf/Qz2q0/gnCHOl/DtH8FPfkHc3UJCUG/1K88h4wvY967pE17Yxu7PYDaG+68Qf/YG8gc/gRc/hnn2UWLTYtoOOV4gv/XHuGceRy5tAQY5v0/jfMm+3f3qF/WZYS0bsuh0p5kpe79YmQ/5dBketP2rhl57/tOkMPGRRx7lxS+8zDf+4d+D9VpF+9OXD9P1Z/GVnEoHinHIzRw587265iSDAOXJgsmpeQNdkoouveISPSX7nNlIlOrAZASH9Bmb962+pwth454zbqeYZ44qsgOh3bO7TJ+BgVEa1IEa7tjLZ6976ynFACn1KDGc0evdjCGNMUqSHN6MMb3nlPg8xqgOtGBUrzlNXpF3TSCm5BhMFLiu7tqcUZSSIEJVVbRdl7IpUhQG+qxH71IOj9acQpdBg0fSIIuou9vFTLbMnrt+thXFKAbQVFKJzJ1kZePAH3wrRH0uNR6mT9kOxjiLhmX52z6U7TE2J1ouMtraYydaQspK6kbUTE2UwKJZ81bTcjKqeHM5x+7tq+dFZLk+xTV6ypm5YJxHmgV86zuExSmummIu7MFnniH6MWZWYU6OMCHC7/8pdnYB+cRDyLNPIpfPw5vvY967hdnZw+/tYv5HfxF2ZhqGAnFU457bJd5/Ebl8DjNTTW9cxaryhVQ43A93ekPSv2Dwbz1VYJPnJCTN9xzWpP/6JqGmHEob3tVwvZ1Z8wCVr/j851/ipz/8Pu+8/guS7128o/wZZzei2QhNe4Ju/9lSuuvkrrbl3qL0YoQpZhELMagqpCIHUjxtkR4jtekdsRgfSSVPUgQK+7VnNp4hl4dRHIrEpcp3IpvYUomeTN7KGe+7m/vZXx/J6A6oqxeIkLSdN4HidEOJrW2Km9ifKDbhL23oqNLuVcapbMap6T0xeykhGUWJClYPjJe1Wc6q94TKPQ28HmNNzz4ffE8v3ibp+SieYJYZ0RckzonJmFPEGFfIdzlbJ6R4PTlUzqradN82mTRZusHUjpm+9CZ9vnOuEDwzpWGzpbgaMe896/VaO91aQ1N5gqmwTot2o0RldxuDibDoGt53hs4Ib3ZLQgyMXYWrxtgxmCD4sSc0Hd2oYvrCJ5BbB5h6RLx1DL/1+5j7LmKuXMBcb+DpB5Qs+dADdPNI9dvfQv7wR7jHHiU8fhX+/h9jdqfYTzxM3JvBqlF6w7jGTkYw8pj9bWS11o64yVNr/GD9MIye8ulLjw2dWTsbOEY2yhvQgZTSKYRS0jTcIr2Ha/pD7S5GpX9D4PKVK3zu5a/wwfvvE5YLulSYmpMhd3hK+cHSsj27/jXSCKQcPdIlIzNwnY2B0tRDVz6j6ZjVYplA6834MybnIJJb22cJajXTMWuBnRkLSVFOgWkGY7rhydGv68zRy1BE4dslO3BvP2m4W+5yGZfCHNTT0WyPx/mBmmPygLDqKdXjkYZVKVRDRNt+RwXLw124DgDGOwatKfQjk+TCUG1yCHoPF0y71maUpJ8LpyLmCcr/6RVj1F7rSC/EJlLE68rRnDEdHe0SEoElSq7Y1hNgKDUS02eRQqdcCTd8Nn1d3EjLOudp27YYpLMhQ0xjuFqtiwqlD4HT+VznImUtyQz4qDrP19Ydt70liuWNZslx07A4XbBergnW43Z3CLZCpmNGn3oaPvspzP1XMK0QP/0U8uknCW9dQ157H7lxzOjdUx587pP89Dvfwv76F5CvfRrZ3yO+eQt34RzxC59E3jpArMNNauzODH9uF789wdQVsgxIE4lJidNYS3A1jav6k1Ty3G04FRuL+m6AdB6vO0J+UnaPVPs22Gwba5LEzeHDDVIP+Go94adeeJEHH39cyZ/OIDal/HVXbnhA1jmwCXDOXvnAI1GZZ824CVrUO5lNy7qPORuHRaLFRJW5aZs1SpzUpxAxAw17fR51AnQwQlq7QSBi0/bJhk4NVzS63opQ4mA9B0myRenzMp9J23gFAqnZJb0DYI3BmjvHc3h9JKaUFSULhtQFfOUIaUJL6Uca1Ga50kWTsk9SFgCaVbrLxAogKetmTA+a5dfmiuVhy+0igzsAiu3ASJV0P8omzdT4jSsvuIEapaZV833pA3QhFKatfkcs2Y/Mni2tzUlpWUMC0oWiFz0wxDFNMkYJlqFVw91k+sJwDoyhQz02l3dl2lTbXeQ31o5HLPjZiO5krRLFCBJSCOoN31ucMmdMdIbrMXLbwo6o7Mr64ATvPKPZhNC04Cu4sI95+QvIzQPsaAv55ZdwL34KThsIHd5Z3Ddr4m6FX0L4jS/hfwXCBwfIbIx/4vPEwxOoHOIqrHdaytK02gYqBuzuDONIRt+zGlWEgYzMcI2cHY88f+kX93y9vkb/n5z91YdcH6Ljlv914+8GOHfuHC+9/BXefesNlifH4FRl3MT+W4zJh0vEW0cIigtpSJbgi/ximxyhLqoKxGKBxD7pYckeSTaaqQGlIyWF9CEkaTll93DYrruErdmzLPhE9jZzjUpEpFfvkPy/wTpkYAyHjkOMwqiuC55LIoze6/oISoAlOtEwKqSGAUa9Eg2bLJaehGUwmKAmU3vM6yltbF8aUlSN5E7XWERdVFswHf1906zJhZkZRL+b687gPf2fWnC6iSkNeCpDrODMIq/qqujhBNnwdcr7+v0g5b/ka2knlxxHJ6NX17WehgPSZNM02s8LNXjDREE2vOqM9pkRYww2RJ5zI55v1uzsbRHmx5jUKULSmERgESPfW61oRjMMkUPxXF8veXi8izGWqh7RLdd6olcG+cnPGF3cRT7+BPb8HtI0mKYBOpgYaIw2Kp0voaoRmWN/ECgHiwABAABJREFU8LMU9jpMWyOrGjubYRZLzHisonWpD5wVUUUBEcxkjDQBOmFeeSL2jnXRh96JMlEOs95y3M1+bITsgioyGHPXsGl4bQYld7t0H2Qjk8HhZ579JN9+4il+/J1vEqJuSCSm7jP9Z3Wxw0ULUb0GPbiSZyQqUVPuIYklqKCaL7gQBRpIr0vvzY0RYjoMxSSJmqQLVTJmMaj8jh6rBX/Uzwop8xPIvAtj1bUyzhRsSUzGi5LSRQrvkIHTILBcLYE+rLuHtQc+Sk+JFA7ldHcJoaAaJbH/EFLaWZLOT95rie8QtaNDft/wfgo+lN1o0klhUordGjJYp3wOreuJsZdX2LjfYVoeiseT8YX0okLIFDRjkJ8zGyuDSe3DUzsZY3qpFNFJEGswIRZdnPyAqlGspMncwnjIMMrV15kbpfFIPnn0NUMRsAJQiqGuPOu2Kc9+cWeHFx57mq3vvEpYzQmrhT5/esZgweN45fAWP3VWO5ZEYWUdP1+veGm6jwmBtltrFjFEXOWI3Rp59zpmHQnLtbrb6yUczeF0DUGwI4+8dw3EYP/eH+iyrj1xe4LsbxH3dzF7u9jdGTIZY0a1uvrLFURD3JrApXPEkznucAXnztHaEUYiQk9AhP4AG15qoj7cIJE2Wsb9BpHgR19ypzkqc5G8juwxaFMIAxF2t7d56Su/zJs//ymHh0f0mWB1hLT/WgrDBzIG1hicq5C21bCpeDN6IEbJNXUdo6qm8p7lajXAz7Jhs7rmixEz6R7Ui4+GYhyNSS3BjIWkpKoiboltjoFULFzGPntvovlNYxOwnbzQrP8tkoHytK8KkTmHxH/Gglxd4LmoT4sadY2uEGsI1qg058AbyK7v3dQeywIbAICStX2sTZK6+jA545ANRYyB2lfUdcVqOZiUNMgbmYKhocshXwonhyFefl02Ehab+FOR2Co2Y3KZi2QvKLuorhgQTI8LmPL/+u/LhjRjRWc9tmw0N8PPzTHsmoCzwqz2PPf0C/zKb/wFHjt3gduv/1+58OZNcOmkwiZynGEJ/MOjA26PJiABsRUB4YPVKbFKYyKBToQmNNRSU41nyO1DzPVj1VUiYva2iHWFPa+ZMhlXmK0JUo+QZz+W2lsHFf+TiF82RHuKHBxilks4XhKtYHd24eoljDNweIK7dQpXzhO7Bts04MaDGj42D5Q09iLDRqJ3ptv7196xoAfGbnOtlN9ICrsH97DJHaKE3Xd8eDR8/OMf55lPf5Y/+d1/qjwxUmF29przyWwMpCr7EGLh9uTP1QL2BHaXZwl0sSG0LVgp6gLWGIyVBGEkL9v0ZVjOq0pHvzcN1tkBxjTM2PXjUTLhac9r5KgJL8kNRTK5OBk9gZQBtzhvCE2jdetBsbQY+7rYD7vuLV0SgnJUsmeS5JBy33tJYUXpGJtxpAJ+pTZFuEE/NUmgeG8kdATou56kXZ29JV2YqkvcdR0xZM7FwBCmida3pjg6L0LTs76zkRgutspXrLom3UZ6TSa+GQ3rcmfgTBr11oPRtH4sa3RwcqcxyNyYjCMNjaeajz404S4brDfiUHnhgauP8Ku//hd54cXP4ycT7HrNyfkdtt5YMooBSbUXRtNw/PMPrvF7rgIMNlpwEYdlZSwRy2g6TlifbvT6yUeoP/s8ZjyGrCZoQbZnmDbCqILRCGs9953c5JU/+gPaZ5+kMmgTxKbBHBwh793EvH9bW4JPx3D1Iu7cDjKbgaugE/jZm8TH7sPuTQhvfEDTeeSRhzfCqg/FiAbe51nDlH/Oh1lvn+40VAZStYIpdsaa3Ajjzu/OOMrZ+zKAWMNsPOaLX/plXv3Rj7h57QOVNzZS9L9yuZXE0IMZBuWtWQ3+i3FKnpVSGRJOk53/5PplQyKiXWpiCAXnyQdelpduQ0cIUmCFKFJeIybpwhuT1C4HfRfPHJIbTWJNvxfJY2YgmqBRUhKAhEgXhvI7H359BKYUS5FojEIuJs0bN4q2jsm3NOSGDCfU5NtNHpV0EeNdyk6lDWuTkUlelTFASFIoVsWu1JANwhrTg+ibKoX5TAVfVUonOENKy5mrGIJW+acK/jxsuXwm4zfDZxKBtmvViOQxHhzAJr3GmN7oGAZeT8FEpDfoZzZWzmwao8zZSxcu8PKXvsYXv/J1dvcvaH2TCOvTU82eeEs378BEPDW+qnh/Puc/Oz3iqBrrgvLJHRfDMgYWq4baC2HqefMhzyPXHVtXLmJ2tqCegnNYY4kjj1gH40oXroVgDfPf2OYPH3udlx5c8rB9RMsN2ghdi3m6gXWr5OWYxrDpYLWknS/wtcdeuYCtVJG0jWve/L1/ysWr/zqu9mykntlMXOR5yV7TWQ95I4EywAl78uTGIidjOtkDCnnRDvbOWe+7/4fNVY4Ijz78MJ/+wpf4J3/3v0KkY9BmovD4dL77ZzPDQzQRcPV29HV56bhkFLLRdF7LR4qmVFr8WSrIJLXTLvc2rJxSRYIM7qPHeUQo3lNe1sY6rLPEblNts3RxJs9FJIYOZ7Pmvo63BYyzxZZ8VBj9EUYpf5n0p3qUcvq4NBd53rNGkkmMTyQzVFVHSPVdgJjjWaNFmDH2uFTSTsobXpvXJcut0aQWJDoNhSKCqVxZEJk4mge0DR3YLLCWLH8yUOXz6RdzFoLL6fey3Aa4hAwWdzak6uiYHqgM/URvnDgkN14UHozJgtn0/sKPcRbrYDau+cynv8jXf+XP88DDj2CM02dOCzgcHrP35vvUISJ1TWUc1J6mdfzmjff4WT1KG8Go205Ih4qB0HFaw9/435/jD16s+Ff/ifC/+DvvUdWG6GqMcYjxHBze4t3330xcF8EinN4f+Jv/7jc4/EvH/Huv/Dv8K/+Hz3L+/BUeev5TWgOHaOumINA17F+8iBfhv77vMn/rY4/w1+an/LXTObZyWGMYP3Q/7/0//w689BIXH3+8oBAbBietu7vlbu7AnAbecPZEiwd79j1lTocfsPk55R5SOFmgxHxf+bMN1N7xhS++zA++9x3effs1bRkVUlhj0sFZDCo9KZEcFZz53vKf6LpJ0YYR06tLphdGa9IMo5GL0T2bsV8LdLn3YuJBlUdJGWGXC9JjT5aMXShrvHfXDJPxlPlyXm7U2V4RBLRmz3ij+zAdLB+eQNDrI2vf9Lv7rBX6nKiQfkBJXo7Q9dkI1V9KXBxJoJeoW2x9NTjdBlIIGSewBiyYmAtcJW1wnbQ8gLn1dulUC8r/6PpKfbFJiN86YuxK6Jlj5XLuGQZynmag/aRqANb74nlFianhY+8d3s0jLURPY1TiNHGwHCrIL6TaNUjyEz3e4ICRNzz++BP82l/4yzz5zHP4epw4HwNXGkN764h6ccLIVEQvGOtp6fj/vf8Wv2UhOsckdFwUuDya8ZPFmk+MR/yb+w/gjeP1+yt+/wXP0Y7lN5875YF/+x8zOc4de3XhPfjiC9TiYDahfec9wnd/yOkjHd3/vIVtaG7f4ORnr3J78RN+///+N7He50VSTsXp9g7N5cv8n/4//w/ef/ABvrVa8+Vv/oAHW0FGDuPHXJiN+P4/+C2+/j/867jRqCxikOK59gXQ/Th/2DUM59JklWtTYiO//s7QfngVz0GEu37rwFDdd/kKL335q/zt//ItWIaiax9DVzY8w+9GKx0wMKprmqbZaCpZ6ClDj830UjzZgE8nE04Wp+lZNjPEEiNtltBJGl/D/VeeU1IwnwvsUog4nUxZr5syNkECi+USxKRGrPaOMQ8SVVbZqHb5et3eCceduf6FVAJ0baT4NQFv1hq6oK+xBnBQVaOk1KiZt5iOtZyhiiLqAmZwzamOUc402KgbVJIiAUDltDYsClpuVtxtowZsMAiV9zRNl9xKUxYRllLAuCGdIL3PYxOyKYbCoFai10DARVJtVSoM7hLbO8v75NQqUXGbzFMS+tM05D7sQoprkhKOUbpA2zZcuHSOX/uVv8BnX/oS29vndIGkEDPfb/ap2mvX2aIjGmhtxBn4o/fe579o13jj+boN/Or+FZ4ZTRmNR/zvXvshBs+jF89zodpibyn8pf/qlH/25TF//Q/3+bf+u38D8+THiBHVR9qeMN7bh7ZFLuwSv/9zDv7mf4F/7V2e+I8u8cP/9jZf/Pd/xoU3btJtTVk+8TT1xx6nfvxhpg8/hL9wHjMZ8c5Pf8LpYsWTzvJBCDzUNuxXBuk6QDsZv/BrX+OHf+v/xTs//TGPfvKFtAgHXqkptqgYzM3T4M5wbmM9b4R/A2yvfEX/eXcDz8tPkmGCu+yu7CFYw4svfoZvf+ePefXHP9aO0cYQY79ec5umSKYp6R12XQaDZcNzquu6b9RqNLQ3Vg/UkLbMfDEvkECfnSueBI4Mv6i0yTCc2vAA6UHsmDDHtm0pGBZC1tHP45WlhYpHm/aTBeqqZjaZ0LVHH+EnfRR5MujApU7Uaq1T+hEhqUbmb1dyYw7FsryCG0y+TZpDPflNPS7nHNkZEokpi2W1fZHJ3JQIEaqxZzJ1nBwvMCF5IwI4S9O0WsRLD2wDqteTXLwUuJRw1NAf6JJB9TOLOsSAsxZf1YpBdV0fChrKiVYMeDSQFAVDCrXqqtJwct0UsNOKTYtAT8x6NOJLX/kqv/Jrv8Hl++6jUCBMv6FyrG/Tf3GxxImGoZOq4s3bt/gnR7f52u4Fvryzx3Pbu5iuo3Y1bVXzCBW/FzvePjnl/P4EtzL8tf/1K/z5fc+/8tTLVF/cR8YTzKqDy+cxI48czzEXdlV54dMf59zjfwP7xg2+eGmPL/xwyenpf4Kc85j5gu23b9O9fpP2H/1z5nu7+I99jPOf/yxPPPUwfHCD/+g3/zH/x2/+Hv+zf+2vMb3vCtLZlDGOnH/maT7zsUf5vb/7d7j8+BNMtraTmZANxnNaOh8FTehlBuvgjJHqw2lKeH3n2+/yLR/yxb2hBCRwbnePr375l3n/zbc5PT3UQ83k7zoDwluDES3uDl0cHLbpHpK10PS+Em4NWSssH6iDztF5z6V12kcP6iQ4Y6nqmnXbpPZJuh9ym4ts4EFKq+1gQokwctInZNzIup7PkyVy0+ErYumajqVZf2gCYXh9ZIdc9S40lMnyIGIV4FaMicKJkFT/hkgpT5lMJiwW2r1gOOlDA9U3AKAvQoRi3Ar/SDQtftIFYlC3wWZDkw4EEn3B5o1vNUUtJmfWMmBP3zYmkTwxWlPWha6ECMZm6gK0bVOARDFKIqtHI+3AW4ytnjYqO55KWIylbbtkCXNKO+VeBL0ja/nlX/0VfuNf+pep3ISchZHBQu/HT6n+YJDFEghEKyxPTrh1+xZ/7dIDPH/pCraLsA7EGGi6FXVVc9V7Vibw09MTnts5r63TBeobS9ZPRqq61g4o05Fm047mmP0ZYezxVtuGu1a0kHY8gknN5N/6N1j/+HXCz9+C+QnVZMpoZ5vqyQcY1VPi/g488gDhtTeY/J//Yz5983Xij97g1hc+y/hzzzN56nGsn2JGhqc+9zl+5z/4v/Hqt77J81/5GtEVxKRfF9nQbDpJmyt36AUN3n/nhtDTXtLpNDyQ7vC0ioH6FzKHADz33PN875nn+M63fl+1iswAwxk+VNEri2AkKWukOU5ru20DRK1QaBptDuGdNrrojdHAQ8p3K5mLpy/I7dHa3J7JDMiqQwpCstbGDHS3pR8bYwdeV2KbD0mu+pVqDEMILFer5Pnde/zurTxZYvokCZKKYzM/Inu8xrh0Clgisdd8AZZLZXMWPaTByZPVJU3yuEwZhH7SoojWxYlAiMTYQlQmqr5IjYlNE5uzcfkONDUsxS21xlKq186kNyOiXUAGpxQMTudkcPuGmYZ23fThZD6N0r1bawkxFCXEkv/JeNqGCyy8+rNXWSyWbO/UZHcoA6Ib28PoaRdDYH10CNKxms9plnOevHSV6XiGbSEmQ2i8gw4ktGxVjrZteHW1oEXw0nFrccQjlx9gvLeDeA9NR7Qec3AbcWNk3eJXHXHbEU8WWuM3HWEsWD/CPfIQo4euIuvPaWYVQzhdKcD+2tu4yUQp/l//LFtvvMXF3/wvufnqz7ly7Yj1K2/hPv9Z6pc+g7Rrdi7dx8PTCd/6J/+QR595htnFi8WbKY+f8E0zGBWR/qc8X9ZsLn+5y4YwlLrWjbV5lrw6/NzeSMod79v4bAPT6ZSXvvJVXn31xxwf3FJ+VhaNT0mjWDLlEWMkhemDzzRS6tJUpikm+owC2xsHmN5YL0WVfgZKBjqK6ntnSIIcKeSDLhs0yU6m2Qh387PndaxrPcEXMRJCxHudE5PKbZzLUYEwGo3vOl75uje1Mh3l2vo5uW1Wxd7EaBW8KFs+4UMM3M7sUVA0k4ZEQCFg6HES9SLSv0fpvS4GbrbJC2PgRpJj7jTwwKgepQkY1galRZpPQtOT8PL8WwyhG+gIJ0OV4+X8XDmmHlY8m3IC6YLQ7rmxhIj5ORgs7HL/6R5/+pOf8L1v/2nRw8nvLCTPcor3J3a0jsV8gbGWnctXGE9naTGpro1Jk6BqCTBzFYbIe6tTVu2aTiK3l8dcuXgZv7+l3YzbDjtfYJZraNbYJiCrDnOwwjYBOx1p+6dxrX+aNHrOK4AaBec8HJzqa3a3sCHiq5qt//5fwzz9ON3nPsX0f/s/Zf9/9dcZ/ZWvYc9NcTsT/GzKpz77Oczrv+C7v//PCJ2QxQXLiEXZMEjFTJyxDcO0dg5h5Mx/Mc3l8HdlrgZ/5oMjg8wf6Ssl79ogPPnEx/n0Z1/COJ8MgCmdn/tSESUpFyjgjEenHpCuVeNMaX4RQsxt5PT5Cgwy8Pbu8P7MhsBiec5sdEz/11KabAyTyQSRTC9IIL2kLKDiGAUjjok6kKsi8to3AqHblM0+e93TKEU6jEtBjxgyMSCm8EVSpbOxSnyMaZBzsWnGAYbgsjHKlbBpkrXEptfadqnJQBbr0i6nWmyYiwmLOwIMQ6YczrardTkpYnJnS8p9MEEha3yn41LVSfVPlzrJ5vcMpU7KzJENpqH2VQppKSfg2UyEMdrlN6fzyYChMTgMXdfyjX/0Dzi5dbt4o2cvQ0osYMB5th57mOm5S8y29/GmxhmHBC3IzRIoA1cAEj5zk8AqxdjeecazCaau0xgKYb2CLvYeWxsI8xWmrojeYkZVkpXpuSfiLKbyemhZkMMT7IVziHdIDKoIsDPFbc3wD19h9PSTykBet0jbILXH7W7xzL/6l/nVjz3Jj7/xjzh4753kLWZvU++vOMr5gMj7aTjH6Omd/9swYwNDf/a/j7xM/vQP95JyeAMwrmteeulLXLrv6p3gc349ICbd5ZkOstljs4m3lisgsqpqH8r21ICe15VS8EMclzOSQYbeGCaMdljonsd/uVyC0W5BClGo4al8jRmYktKII+Naaa9kOKVr/wxGSeVK8uTml6eWv9nSGsqUBwTvtaFheiKMgLcWX1UKzhnL9taudhdNaXCfB9tQTq78cFk3yWVPS+wdp0FeID2x3DCu6959yidsnsABLlRcsMQyzwsixEAXQ6IKDLy19L+sp2QFTBTa1VpTKGnS0yGimBS9exxj0PcMdohAys5Y3nv7Tf7w9/4pxE49KM5gGxtxDHRBcLZGjFcaRdtgysEgiXOlBLoQOsW6ggFxSIDrpwdU3nPu/DnixR2oPKbrsEdzZTrHiDQt4egUO/KY2qswne3nV4fQpDZSFpwjLpeqDLA7w6w7OFlibp3AYq3j4B1mUmOqCmfQ40cMcbXGRcMLf/FXuHDrNt/8xj+kXS+BnmWdVRh0H276THfDgu5Y10NDkufiQ97SH2Kbgx/v/RXlXvJ3PHD/g3z+iy9T1V7DXmNxafvlLG/5zvS/s57MZua4f1bNtkmxc8XhMcqoxpw5IEVK84BCDJb+IO0/c3gI996OOlsmdQJK/4l6RAWCwaSaPuVmZRgwCxfe67q3pySawozG6KmYB02McodS1wNNLapbPewNlU+euq4RcmskODg4QMgsbattfYDcNE/oLffmZTYXoTlThJsNG7BumuTylyi0eDDFEA3Czf7jTdlsNm+4jCNljCK7olFKSDikT3jntazAGDIL3g68uxIaGJPqhSQVOkLE8k9/93d4/52302bJq+zsKa4HQzUZEaxJLFowzuGqqrxWF4GWyKSqYnSDRzoiy2aNWIu7uIedbcM6YA5OoNYyGhMjrFvMuFK+lsvEOij1Nem/nOyQ0GFPV7C/DZUlLJb6+1fexHzvp5ijU91k1hC3x8h0rJyy77yKfOunSLtm9/FHef6Bh/jZH/8Jb732askA5QMylvEzJRT/KGMEd/ds+nLRj35PDvnyG/5FvlNQQPqzn3mJBx98TDdwAmxsFujvnZYCXdxBSTCba6h4M/kwzyFplumxubYyAejpXkjzFEUVW0vkMTBGJkmkuLtkpEv4mtZu2zY4b6nrqihaGgu+tozqanAC53u893jd0yj5qvr/M/ffwZ4lWX4f9klzzc88X++Vr64u0977njbjdnZmMVgsFgBBeBIgIEIgIJBBURQUCioUUogSGQiZkEJCBBhBgBAQi10sFktgbJvpMT2z09PTPe297y7/7M9dk5n6IzPvve9VdfXsLv/Q7Xj96v3MNZknT57zPed8D0kka6OjmV0LABpjfcq68Z05uu6ODNqSjtmppCAN5p8Qqh2Q6JZEN6prnnf8e4druHnABbA6mMphccTykxhR89njzodDpWpNv4BdCQeRwC26jAqBsp59M1pZe3dYiIuDxsoyznlyq2g1hXqfiBJJ4ZMnkSLSfPtTNXCa49L6Ok985zu+HTpuNxPBniOZH2BT7fE4IZFJitAaKTWxv7wLeIWUoklE9Vif4tJkm7V9ayT71kAkuI0trAWpEwKTF6Kuccq38nbGtkIlCe2+O9uzdVBZXGlw+xZDdreCxQHi8CocPUKysoy8uIl79SPks+9gX/4AN57CQo588lncP/49ePd9Thxew22u86NvfZNyPOq4Nb+EmfL/h8fa6hoPPvwl0nyAxRfbSoHPwO6sxC71cfeIGGiDZ4pQexms/0YO42/XOHS71nDz20ER6KTj4S0d18ij9E4E/bzX0CzH78eE44jVmcg7pvyPkJLJZIqp8fBPo5uubipdVSn5gZFX1NhC+MxnpVUout398CIoAwfMAsUJ0OnX5q2M6OqJjgm7F8fpXhdaTiKaa9JYV9H6iaFIKUNFdEPkthvQjCarCmUuXfI18DuBiOemuaS/l5B9bqUg0OP4kpi4WzjXdgAOCjpG4CKuIKUktm9udbHjuZ8/yztvvx4/3dnJxa7/yyT174qAgwXLAeHpWL2Ah5QICSNTYZRAa4XWmrOjDQ5cexzmh9hPziFmhaerrR2u4fp2yNp6dy7u6DJaR7Quq7VYY3BliVyZ991NjIV+CtJbxE7A9Y8+wvsvvuTr9a5ZQZ5YRQx7yGuPU339XvjFG7h/9K9w5y9Ry5o3Xn2JN156oSkAF+00fOrRyGGcY3ZvrN3jD6vi/jAY1K4kTeG48+67ue6W23xQIDA7WulworVkoqfYguy7r3el+23kOrq34bXI5y5FhEDiuHQt/DhSBANLdt6HQb/PbDYDR2uRC7FrbI2xgY/fgTAYYykK3x2ZTi883JU8oN3H1d23OiZHRfBKNItRBvpaKfyCdwFP2AUKd24eFzY64fvGieDq1XuQ+Njmukmf32M6m9r4tjLRZYjXiAos4kWdCa6DoolRMe/rtvfq3bsWf/I9z9sSkIYu1w+E99OlIElT/8y07zfdXqTo9DTzr2Vp5p8r3LsMJnM0jxugExhNdvjOt7/JbDQhNtZs59JblVYAKsUJhXM+EGArE2qtgoJwvpgaASJVfBjctaEUpP3Mk3YNeogz6zCe4fp9bOmtIekCkK0UWF9SJJwLWFd45G4krPJkgC4JlhEOmacIYxDGINMEkWpUkrIzGWHzBPnmWdw3n4f/17ew/7ffI03m4D//D3BH97P5yTq1TLBFwVOPf5vJ9o4fLtcqmaigrmRVNGPFbi/9MjkPlsXeCNyVjispoat9b+/r83NDPvfIo8zNLSCVD5k3bbuDa40STX2fL88KhoG40jkjxhkUSag9jXJbB6srYmfOtYpEEFNyaM8VqJ9lUEoWwXg6baLUSmuPU4bPdgvXu4onpt349k5RxuGzWCfhs4DuK/m04DOIa4s0oS1Mopui127HkRbdF54VQEgciiRJdk1UN7LVBRZFx3ICH5nTjbLyD+xCsqWwXsNHG9YrC4noVEPH+2t2m8YaCnxRAX+JllXEX1qF4LWdDT5bWVQ4Q1NKI1zr5nmXzy/YhirYVD6/RIlGySM6TS1p+3NZ4NWXX+HlXzzX4CndI8gZephjexkIiXEVsVYwtq9qd0IYFRWviwojYTVNmZYTtssZh5YPYIsCuzhATkqoDU4HAZKBOAwH1isdagvWNvTGLgZEQi6a7Ocgpad6Xd+E0QQnJW6+h+v1MLaG8YzqD17DzOW4r9yB+MtfhN+4H3doBXHDtYj/8M+Q3nQtc5W/jw/eeYsXfvoH2NrgOrWH7Xh088u6ETjXWqZXFPL2+1c6PktJfdp7V7OgbrjxZm6+456w+UYLuoUnhPCbvpSKXtYj0Qk+Dccrm256TYvRBDXTcZOEkC2ALmjdPOIeGpRQtHQFxMiFA2hkusVGTaSkds5jyMailec4a72IQAIXLa6GVdW/n2bpp44NfCbQ3YbgG7eGeD/WJwbiAWEtVbP4mokJhblC+NClCNXKzvko3eVKL9IbEMxOGvcxLmAZ6DTahMcwFq7NOG92HOv8IgrgnSdsb9MH4kS1jpwMSsdTiLpmkP0/pBMNAC47QhCLaSNm1IRmArCvhLdsXAgMRAGM55YOpG0nI0ZG6qrkse98k82t9ZAvFScg3DsOPehj8hxblZh6hjEFztU+ohXc4yRJQCi2ZwWXwrMuzc2TrixRmZp5oRBzc4hZjbEVIhEIU/sC4Do0H4hAaejoEkuLAIS1iMI3vnSpRuAQ22PkJ+vY7S3EZOwXy9YU99xryKdfhn5G8vlb0cdWkbbGTTewF87CE88g/ofH0L/1PW578EEemZsntX4T/P5j32bz0kXP/NkZw+7vK1oyl6mwz1Y23Xn/tL8/67iSeydwDNOchx76AgtLK40FI5ForZs29hHsritDP+uhXLPEG+VFdM/8Kmw3Rku7a0W5RuKkJFSpoLXqgqH+/c5//lsSiW7O68LGjaVjqUrqylCWdWs9OYIii5HFeI9+fqqq5GrHZ2JKu/zaYGpK4a0WEUFw6xeskq1lkyRpANpapSGCiRx7wcXPxmtBjBK4plmAH/jWHSS6XcGcSIQK+Rq7K7eFC9w1Ujb5NH74ZbBsCC5lJxQrvd8v/Ql23aOMJqnzqJBzthlwGc1n53979j/aPKdw81GgRFBqCtGkB/jz+MYAwjikFTgnef+D9/nJ0z8IpGDxfuLkCVTWxyQZtqqRgYvYBfIKiUK4YEinKR8VIza1IrVwdGEe5noorZGDAZgaN51CL8WkElfUnpvdhUz80I0mClaQOIQAW9aBm12CtdjpFFuUOGlx585ilMFcuIj74c9gfRN38zEwBt5+H/uNH1L9t/8c+999BzkqcEf3I/7kA4ivP4DWKfd/9VEOFhVaSC6dv8DT33sKU9adDfLKimiXHF/13asff6j8pe4196yd5nxhFk9ce4J7HngIpRO00Cghm6YQcQMX1pdgjUZjL7MmWO2N1dNu+goi5uxl1for+W4pMnRGEY3iMCZG5VpLK1pjAhWCKwJEDOHHPBx8G3rn03Mi1W4wtxr4wq9bGM4PkYny5b9SkaYpvV7vqmN31TITHfxLX5TrrQwlBVTGN1IEYltoE8DYJvlRQBIGMKqgvTkKznVKNoJZGbGhqqqJ5mUE3NqyjDBYBD/VtS5g47FasMa7PUr4UGVMPgtTsEtgBDShXh/Y84Bxk8kd7sX3fYvgf3Ttdou9cAGMx2Hq0Drb2kAKEGhd4k4jaATLEZPWok/hy2B+8OQT3Hn33ew/eIQWNAzWgZK+kaPUKJV6pe4MWmhcEGIBIB3v7UyYphmLznDbwUN8+OYb7D9wiF5/4MP4w55//nEFc31sKrGJDLlWPowsLD6i1g2RWudJ4JzzrtrWGKEV7o334IWXEOk7VGmOvuV63GIP8cx7iLLGfHgRtbpC8mevQazM4wY97GIfl2c4I2Gxz6Fhn5P5d/jIghCWZ378A+68/z4OXXPcRxA/RVl8Fi4UakYbhfWHVTq/7LE7siUa6zLRCfc9+Cgv/+IXnPngA5x1lKE1tgwdSCrjo9Ux49/XTcY1YoPF4g+P+QTIwHksFBvCKh1u8Ab2CZtNXDAC4emfVZQZv+a09vLqDbc230g1JWXQXdR5nqOUYjqe4KxltL0DHaYNIQRVWV11zK7uvrX3HIiiQp1a2CVltGYC+O0CziCM9XVXuIbfWghBlmW7Jj9mHLcZ4G3RbDOJ4UG7aL/X5W0BR6QS8Q8kQhjfnz9JUpRUJFL7bzvf2jqG/qNKck4Gk7P1oaWLvevacfcKMvrz4R6DS9jJW6euauqqCkC7CYRxvolCkqQdC1GEMQg7TWO5CaKqv3DpIt9/6klM7AXXvO8tQoxDqgQhtU85UBmOTk6Rg5m1vFhPMU6yIhRrQlNc3EJai5iOcUXtXcva4ZSvp1JIhEqboEGTQmHB1RZXGV/rZh1iViDOb+A2J55Z4NI5eOJHVK++76N9d57GXjiP/Z3vs7YtSYdDpstD5PEjiKOHsCsLMMy9KNUWKWr0sEcyN8dN1xwhKycYJKOdTb733W9SzqbNnO9NMtyrCC6zdPZY1XuPLnD9aT9/1MNHSj3Z3pGDB3nwkc+j8xQnvYUtkSihkEIjpdrVscQf0rMJOIkjbJzCYoTFYDHOdnqxuYAxtUmSuFBn2sVmhcAGgFxFiFoInDOB8ytAKs26AVwoEwsdYiKeO5sWjHdG4FxTduUMgVtNUhaekvdqx1WVkgwRviZvwvlEqaiN21R0yJI0PIiPkMUks1gM65xrutzuLcwlhIqbybatYFjrKMuqsS48V5rtDJYLLgt4y8q7Fu1vLwr+3QjghfPLqAC7dXbgmmhXIKhyBLfSthZCsFYay8Z57AgIWe0JNC6df08JQZZoYougaDW16Xu7HNBw877A9Sc//BEfvvduY1bbiGdJ3+hABNK9YBYRM6QdDpFoNkY7vBswuNU0wUwmTIRlYTgHOkMsLWDn+iAV9DKvErWnKfa3E9IsaospKlxRI0qHm9XYzRH2/IaPWC4u4ooZ5gfPURUG9ae+iDm0RvHkT7AXtlF33Ep29DDleMyln/0C8+IH2Dc/wb5/AffmGXj5LPbcFtYIrEowg5SymHniOGeojeUXz/2cd994rXE9xKfI+JWsn8YivZrg/09wXCltoIEoAqgshePee+/n2pOnG4uv7aPoUNKRhMTimAsWky4FgPCOekM3EiNvEPIA40bulZR0LdTkhMKzmAbXoBsAIpazS2rrgqvnc291mqIz7QMhAXtoC9BojRQEKk09pQmWPM18PeQvcVyd5G3XALevxzZKQsRMWktRFI214IRDBxPQEMDkQO3RVUheMbQntiEBc/fVYxNKPzCRgkGE7wdPq+1YAs2k+MUbaCDoUCu0DxYsAK80rIM8T32JSVU3ldlAh+KzuS2i5eqc8wBlt16oEUbRfAY8gZfvUuExOlt7Jkuv8Bq1Gc7jn8E5GI1GPPXk4xw5ehyd5y2mgsPZGmsKhKuRwo98HBgpNU4kvLm9zYbSSGe4dXGVlWOH+Ojpx/nVh77okyATgSwqH91RAoQKWFob9sUBpvaK2QhcWeFGU2SWhBKVDMox9pkXcFKh776R+ukXEElOsrSAWp5DLGa4c1tQlFTfeQr7xM8xy4voQ/txxw/CzadgZ4x46mXkdfvRNxxn8dAheh9+7Hm9gNms4MnHHuOak6fpDeaaJRTl8VPlObrqorUe/rhO26e5fZ91H/H9xYUFHnr0i3z03nuMtreb9VFjCChFKK8JCia6X2EPizil/4QLpU2E2vZQHBbOYUSo6xTeBXLxXvwZaaxv2vUU+y36Z7KUVYGvJFLUHTI5ITxEMch6TIsCK2A2qxr+qEloCYXwjAFXO67+rvBglc8rbM3W2Lq3TUAMPmow7XRkERCtVo9E5v7h/E9c9NHt08rjEq5TrgI0tLFCeIXnZDA7w8Vj9raVDqfAipDzKtpuDRFBEJ2/hOtEvYKuKouSsqgDvuTabiVaNXhXVGxtn6tOXVLAoXz+leuYwLTPEp65LivSJEHKPWBic7jGKrTW8vOfP8Mbr73SKL/mO9b6tkdaN1FJr8RNaO9jeWk6YaoE+xw8sLRGNqlxVY1LMkQ/RxUFOIvopz7apqW3mhLlC2pjxNOBKCrc9thzcC/P4fYvwnwfJwXjJ3+Ae/IPsD95kenvPo69sI4cDhD7l3E7Be6lN3Hvnve4xOGjiBtvgpUVyp0R9U9+gfsnv4f8/tOIQ0tUP36V6h//DjfcdRunlSJrmA/gzVdf5pUXnsda3yyhEdmrANNXitbtff9KymSv1dNuxld257rnv9r7cQ5vuvU2brj5FqQCpUAIX94hhGgDO4Sor4tYausJND+4xp2CFsdxgpBf1tZrKkAHd0zEAvLuM9NR3uHfSqgQ0JGkOg21rD5ZuHIWK2EwGJBmiSdnlK1yc86RZRngPlMpfUbfN/+/2NrFBN5sLTVVVWKcJ/EXBO3rAmAWKRYCw11l6sbSiDuUJz9vZyZ2aQjGwS6rIbpgxrpdHXdjJnQcxUAsG7RkoFETEqEEtg4TI2JEwmtFSdw1/U7RRiP8NUWY+dqYxm1FxLo2/5x1XaOVbkHXQJMbrSmCNSmEp/lIAgezd9q80oj4mjEGFxLhfLvkeF+WyXTCd7/zTY6fPE0+HHplXJQwnvnOI0YglcNVvq041iGzhI8nW/zUVliRc1pprplb4uxrrwGwmGS4usZmuV8AIbXDRTA/vGalbNIrXF0jsgSxMMAlGbgKsVOz9eIvGP2z3yGflWTHryd98G70yjziwgbi3CW4/TTccC1SKMQf/Gvkrz+KvvtuLAarJdWFdcwPfo566S3Ss+uo3/wiZjIle+xZvn7nHbzzzB8wzYfUpsYgeerJxzh9403MLy01gv9Zxx8HD+oee62yT1Nmv8wxN+jz4Be/xBtvvMp4a4MYoXXgx9s5RNPPzZ/Tp6XIUKAZiA1Fxz2LsEm0fjpWYWsl+hq8GMrp5hV22HEaQN3zpHl5LGYzH2FXUNahWSaOcxuXiCkF0RKLntasmCIEFEVx1fG4evIkIvQ/k6gAagtHU9He5C0EsNfiKSRiAa9U0i/mcGNdxaS1ah7E4qidpTKeTjeEvy6feBGxHQKfUxx415q1zc6kwPnaOt+Sxvdtr5xpfHriQAuBTjRRCfnSnbA7BRZAZ6K1Jpu5CvMXUvedt+Kcx7o8eZy/Tu38M0UPP+4wSil6PQ/iW2sbhgUR7PRdu6DwQOJrr7/M88/9FEKukCtKlDEtToUIIVuNIwEcPzx3hg8SibaOu/tD0s0dRutbfkH0B7iiQkR+5drgEglaxhR87xiY2ucTSRD9HOZ6vpC6rjAXtjGbl9j6H36H/kQyd/8X6J86hR5vIt54D7F/Affl+7GrK/DGh/D6u1DWiO0t5Pom8tIOyfqE3uIC+V/7DcT/7M9SHVjC/tvvkR5YJf3y/VwjBjyoBmhn0CFB8MN33+XZP/jJFZNLP1Wm9yiKy9JePgUL+p8M6N57noB5nLr2NHfccY8vUMc18+/LJEWwgggWTUg9cQJpgtUjCbVoYc6C24RwvlJAGFysyWyeKzB1BOsp5tkFFAsraywWIxyVNWF9C5zxhfqzsqIKwa8ssHLEtejtiO54xRyrz1bWV1VKJiiKqq78zi5lE55swvnCZ0rXob2SFD6EaUxNWdf+QToYS3QtTEiiDOPvf2IJR+emo2KyQUlJIRvw3AYlqZtCDNESuTk69AsiTI4v3BUhFyqmW1gBs6rAOBMKJeNSjGZx2CmCEvbc//75tQ40HiIkGAraZp3BMmvMVWHJspQsS4Iygtls1rh/0+mUug7RBcwuYDTPEwCqsubxb3+TzUsX/Q5JjKx4s9izCnq/VErJuemY7xUzaiVZMo67FheoRzuMqin9NEcoiZqWiJ2JTy2owQQuKYdrGlVKqUAniDzDptpbocbiNnYQeY+tZ54le/tj5oaLiPV1ZO1A53D3LXDkGGJ9G3X2Im5hiDp9lCN338mol1IfPQhHDmKPHcTtX4MkQd16A+rv/nns3Tdhn38BffwE/V99mBtuPMVKUXoXxTpsVfP0977HpfMXmwXf/f1pSmGvcriSsvgs5XP5tT79O1c7nwuIUS/PeOgLX2J57YAPmMgoA6aBIjwoYUCGglwncE6R6Kwpm3JWBnjENWZTzOETUVbCPVnnC8gjJOLLnGxYsyCs39TrUMwug/lvhcEKS5InoAW1NRSzggimC0TrKhLhkWDx28+2Vq9uKTmPBRWzwic82tZS8grCdxAR0u/60SIyjd/SzEqjxHbtQKbNwI69zBrgLlpJAX+JhYAxCgh+kJrSBqWD0oiRNBdYLW3Ip+jk/0jZXMd/MgpImMegfCK3U2TpEwS8SnpQ3NQ1dVk1dUIIfzVf9S1QiSbNMpRWAZuzKA0nT51mdf8axljqqm5MbhBBWQeGgXBdZy2z6azB2T748AN+/MOnMHWJzDNMqkBpnPKlCf4+PTnJs5fO8mamcEJwXaY5mPTBwoebFzmy/yBqVmMHwYXDR9ycDMluhLwshMeYEt3QtWAtbnsCgx6m2MR850esLB9A5jl6bR9uPkeePIYb5LhhD7d/BXf8EMz3UQ4W1tZ4+4c/RG5t+7be0xmsb+BKg5ICNTeH/vO/gllYgDNn4OAap7/8BY4Lh6JG4jHIC+fP8sOnnsCELOHomnwWrnO149Owpj/OOT/jiuAMhw8f5r77HyFRSZBNgSVymnmVRMBJhQIjDE4YyqKkqnwVUHfhef58ECHdJS53ayOltWcq8P3eItu2XyvR/XJ+fwvF2K5pRukcFONZyGX060gKn9eUpSlzc3P++yLyYPmjmyv1acdnuG+QaE2app4ixLc6bZUKNNrYWp+bZCrTulUdDGk3Ha7/Xsx7wNoG74nfMViMiEWnoUdaoBkRiDZnRgjqum4idLFsxEHDJdMOhmtKPRqT0oIwLUeOxXYUj2sa8vkntt4iEt4asdLncgXIq8GfLH6GhBTUZYG0NYmEw4cO8Wf//F/hr/xH/wl/+t/7awwXFxvS9gjVRqKDvYdxLVugsZbvPfk45z75iCRPEXNDUKGrrLHBvYZCOZ6ejKiURjvHvcN5+pUJFxGYqvb9uoQEpZG9XshVCZuDTnA6DaUj4Mrasz0Yi6sq5CDDDjPKx3/C/FbhI337Vzw+leW4qoaPziHPXsSub2AvbiGyDHTqi3cBMZ7AhUuoaYEc9JAhgVA4h+zlpF+6F9ZHuLJg4ZrD3Lb/EImzyLBYrbH85AdP8cmHH7SbjPuUOriOMrkSaN099v69O6zfvtYkRLqYcHj57F3JLbzcRfRr7cEHH+Tg0eP4fP8QHXbBJW8kMZAFNi8FXFRCDE7FxAdBcNMiWSHWW18xGBT4vqP8R2jDRTXS8IaLlkdKOLAG4SzFtAjxGa/Y6rqirGZs72x6pdeMe+RZu4Jw7zk+s/YtDqoTPqvbWNNOLGDrFs9oEh875kd0Tay1TZ7SoN9vuJdih8+ogSO+EivbjXCtCxhUtzMtANy9xi4BCKs7CmkjUNFqCztA/FtEkzcUmQoHgzxvvhsVD8G3ty64f4TXwr/aKAlYY5DCsDQ3x69+9ev8nb//v+KRz3+ZXi/n1KnruPW2e/y1ZOuiWqAOQtOdB089HJgVjGV9fZ3vP/kYDoPo91FS+2LJOrBlCsXzl87xM62ZKcGqcTwwv+Qzh61hq5hwcGnVR9dsTZ0arBkjbOWjmKnE9hLcMPNKaOqZNZ2Wvo2V1iAV7oOPkE/8lFT0kUkOuo9yBlf5tubqyBpuad5biwIYe+tK9nu+fhKHlRJnahhXgN+orAqBk337ECcPISYlYlRzw/WnmS8rcJbaVFS2YLSzzvce+zZVMeNKQf5f1qLZq5y6CuzTPr9bAq6CQQXZadZGNEPiQgl46draGp/7/JfIsl7wLFyji7pKzIfyAx4rWkXisFjnFYbXUX5jTtKkye2LwiyEaOALF9aZJ/r3G6/WIXQUyossFqkEg14/QCOiuabDNK95ix6U0iSpBmFJkrZs7LM002d2MzHBeola23UmyDrXRs1czOB0HojENdiQtbZp6Q2e67cbSdi1Y9FG0SLoHXl8hFJNkldkqHTh+3TcsygE0QoJUrPrueKn4zjFBLNoqjhnqWKNnnPYiNfEvI2AtTRRRyFa9kApyRJFpiQ333IPX/7q1zl24jRS6kbA+lnCQ49+kddffZGLF840JF/ezY2UJy6EawlkafEzFofix08/zf333MXq4gKVAGm9cCTOMqsU39m8wCgbII3hgd4cB3UPioqqqpmUM+bTHsI4tj/4iOm58yweOki6tIIY9jFLC8gsQeYZdnmlIbX35UZ+TOrKUTz9LMnEYvO+T02wFlvWuCwDrXCXxrhXP4JMwk0n4d1P4NV3ce9/DFkCMoEXXsfmKeLWE7hDK353jiajErhDy6jSYranrJ0+zeL3H+cSltKZ4GpIXnj+Z9x9/4PccNtdTarGlY4rWUafld/UBcKhXVO7dFW7R17pqp/yt9v9SjjhnXfezXPPPsMbLz2HDSG1GL31sITHZoIRhXHGexwutiLzNykRwVaxVFXRbH4ykh4SM7zatRitGuOAKlyAMF4CjKnZGe0gAqFhW4AQ3DIXm1JK6qpq8v3STGGrOgTOrq6Url6QG8AzFYCrBjwLD2KFbyMMHtxuZsu5Jo3d32+MOxF2eoN1bWGuC/+On/eNGr1bFYEzoMkZCuxIzWA2SjMMiAnh+4gvxVykqNxMY5WEtLSIQ9OxpqSgtDW1a93ILu2qcy3jQbTIEISUCcupUyf5S3/jb/OX/9b/nGOnr/eLudml/OeuPXGCO+9/GKUSX1AZ8pmUED5nqyO2Io6LlCjpw8M7oxFPfOvbZPM5WiY4Z9FOYVLNKzvneUYnVNKy4uCrC/ugrr21E3ZJOy0oL21h1kek+ZDshmup5xQ75Qy1ugxrS76bCZ4+19UGXOhik6SIfoI6s4FaWkIg0L0cMS2waYawAjEuESuLVMogXngdWVVwx03YfSvUH5xBnN9GPPcm7sRR3KFVxCtvw8aWz38KuTM+cCF9MfjKHP0bjrM2v4rEIsNcWQeT6YwnHvsOk9FOIw9d2d9rZXRf36ugPnU9dK2eriWEI1Z4f5ZV1jWS4u/Gug9rx3MufYnecB4tPM+1VCH3zHve7bPQbMWdjd3tDun7B/P3KQNEEQwAH3Wmifxa1xbUWXuF5xHBso9uHPFhdlt00f3zcisppmVDAvfHir5FF01Gdyg8iLE+HC1sJAsPg6o9cwDQLtj4LEr5ThfaJ+HVkZcFmp5w3eu6cF1pA+ovA2AWNwLhLRLT4Ei7By8KTKJ1iAjGbG8XaHHD7HYzzOOgSEmmk0YROxtzasOzhPEYDAZN1EMF5b22vMqf/jN/kb/5t/9T7rr3QdKs3zATdC9iBSTS8tBDj3Dw8LFg2Sm0VNRV3TQK7O6mrdvswi7peOOF55m98yaiLBDGYAQYJ/nm+iW2pEI7yb1Jwo2DIaKsEQLOjDaYS3v0ZEIyyOnPD0gSiZsWOAOzsvCNKPHjQ6q9q1vWmEQhUo1LFeaTsyRvnEEajV2co8RjcHLqhU9WNTZLSPavYccF7rcfx735BvKeG9j361/BlhX1uYuI3/kW0lSYW64BJ3CzEtHAAq4ZAiE1Kp+jd++d3tINY+FbxBvefutVXvnFzxv33l5h7K4k41f6+7Mwpt3GT9cnu1yxXbYE3e7PNy8Rs/8tN918MzfcdjtSaZr0ABUqK1z7PC6sw8Zo6NxrU34iaJRNNyk5tiFzQFmWnn45eDCXY3HRPaTNJpehjEnER9m9DmO00Mna47Adz+lqx9WVUsCCameprUUq1Zh3AodyFhk6Xthw47sUxB6fvMGoaBVZmqa7tH5zCFqKWdfpz9VMYtyhRPOZgPO1tLp4toFIIRIrmp0jYFidaEMYWYnHuaqy9JmvwZXqJA0HV1VSVRXWeS6ppWGPRz73EH/77/x9fvXX/hSDxWU/uWGyEK3F17RgkoJDB9e478HPo9Mcay1lVTU7po/qyUZJx7H3rmvt3ceqQJ0/jyunfi605M2NSzyHpVKCRef4zeUDqKr2rqYQVLZGa83c3BBtamrhKMop9ZlzKGNZWFnCzma4qsDW+KTx2RSEx5RcqhBKI8+ew00d9HNUUSEWh4hrDvjMd2MwCkRZwbGDuJtPwc4I8Xs/gh/8gkNHT3DmwidMbj2Juf0U9p/+a8Q/+wbizFmwBjetcGXgf1fCk/kpKBDcf9fdHE4ytAMwPlhhoZzOePI732J7/ZJXWkLskpdGbnYpGEGk4WiTe65sMTXfC4m2u4i5dn/yl/hr7/daJSWlZNjPefjhLzK/sNKaVHiFFTHXplhBtBv5ZWcTnazqmIuG8HNaW4pQyxoeOmC3cSNwzTqBkJMY7k9IidKquZiw/rPdpgoAOpC/WWFBOoS6fET2Hp9RZuJD1DpNUFo31fo+k1qACBGQ6IfWVUhUDKBfEAobQDdX1YjQSywmUnazO108V4AT4i7QBZuF/1BbwNgxN1109TqfxznyPG/oe33tj+j48KHSuuNyxs4jThDC+aGiurFQI/Bs0Vpw8rrT/OX/+O/x5/763+LYyZNeoG33Hvy1XANiESbe38d9D9zPqVM3k2pJqlTDqBnl3oT1Yhvl1rqaqxbm6mBqC4mrLY9tXOBSnqON5Iup4sb+0APgAgSSyhoG/R5JL8dmmiTvs11XbNc1MkvR/R5YiTm7QW1rL1DbY+zODkJLhPWBifrnryP7fYRSuCRFjy3izDa2NDAqvat8fh0ubaLuuQF76gi2LnH/7kfwjaex0ynuJy8hH7kbe9dNIDPcB2fhzHlsOYO6wpYVkhSX9nBOYHPNbadP8hunb2TeWBITwOAQ/v7ow4/48dM/xJqqEYqrgdV0waA9n7m6K+aaX2LPf63v1H62o1cigNRc90qXcc5x8tpT3HbXfSA0WNGE+PfebxceiX83blwHQolKpymSZ/dGj3Nt7WmwvHwdnexerglQRSXljYbAnx42fIILXZd1OFdIZ8BSX13rXB3ojgu1rCqUUozH4/ZNIRr+7tpUICx53qOuDBDIp4jgd9QywS3bw7+9a/cKIHY33BozTaML5aBJw4/Rulhs2+5d8buwMxoFIDlgX038PewoNuY0AapNKEt0ghKCumr5X5zx4fZUwtraQb78K7/KvQ88TG9uMUxvk7Tfcj+Fe7YEHN22UiiAlaUFHn7083zw7mvMJiOP0wkPKltnwXhT3HcjceFZQQnLNXmPdFqhkVjleHe8w09dRWkSDgjHb+w7gqx8m2YhPNnXB1sXufvE9UjlaU6M1mRCoRHUpmL23OvMfel+mJXIaYnYmWE3dhBbO4gjB32qwLREvnkOshSv6rRPvisrhEmx5Qy5dgjmBj7SNjeH/Atf9xtTliMuXoBn/i3qzz2KOLCE+vVH4OmX4ZrDOCWR2wWIFPoZbv8idjSBacXQgUo0t9x7GweeeZqLShGDHA6FMYYffu8JbrvzLg4euWYX/hJlDfZaQt4SiNUC0aLdmwZw+XkcnfTAXee6/Ht+E3Kd87eWVvxmxwUEskzxwEOP8srLL3Lh4w897ipkE+QJq72xFHF4qiDZ3veuFmQQ3MMIXIvGAxBRUQbtGXsFehOjxYica9k+bF37DVwIkixr0nJc1MAiBMasr3ow1voEaXF1rfQZOiu4R9ZiTRtyb7ifw3N4MvHEWyQqKo9oEdDuVpGOdq/va0xIf4dIIRv3L+cInWz9Z+O/ogJqzuVBmdZcx7VsnyLiRzSf8dapC4oyBjVDAln4TmUqjKn9jSiJ0JI0UawsLPDlr3yNv/ef/5c8/Cu/Rm9uESEsSvjJbK4XBYOIb4R4RwfH8pey3Hb7rdx4y90QlIfAef4kY5t7jINi8f58YizHVUbiHE4pbKp5/Nw5Ps4ylBR8Ne9xUvWRde0jjkEQfa2dDuFmgchTMgN5Nke5PiK/60bMuU2ShQXQElsb2NiGfoZ94wPsxxdxicCtLSCk8hzdkWdr3zzccR3y/jsxS/ugN8QsDGH/EuKag3B4DTEcNDMslucQ8wPE/jXs2hx8+CHi3Y+wlBhrvJuxPkJujxGzCm2BRHLgntu5a+0AAykYplmghfXjvbF+gR88+ZhvMEFMHISoRERDsdeRc/BzdzkC1Mj9nlcaJdO0qI44T0e5NJ9zzez7577MhWm3U9dEvCxHDh/mgYc/j0pSX+DaBSeDwhWRKlcQ8gkjtEHr2l3BHGs8j7BRx6YQvV6/oc1tcaPdCtoaG+ANSS/PqauqqV2NeK2UkjxNfc6ZDe3KrPMww1WOz0gJkBhjdrUfklKilOpEyxzO+TZGO6OJtxCkQNi2AWPMv3G4xh3vhmb3hu07hm1jUTlrYyFQM8HN4HYFJixar6MCOB4AQal8y/G4KUjhgXIZiejj7hG+I6WPNCkhwFl6ieTWm+/gV77+mxy/9rRvMCB82Uo3P8Yra9HgXPF+uja2606ME/QHfb705V/hvbfeYH3jjGf6IwgMvrBZhuRVKRXWGnLrWJUaZ0HmmrfPXuQpW2LzOY6VFX9i9SDClCH3xHfLnZkaYwx56bBVRRI2EWMsyeKQpJ8y2dpmcOP1GGuRkwQ2NiHPEcePwr4lXCIR/Qx37X7ce29g54fIg4u4Y/uwuYBXXqF+7CPKixepxyOmYsrs4EH0HbfRv/N2Fm+9EbfkWS7dtITaIoZ99BcexK1v4C5cQm6VsD/H9fuUeUaKRBjjmRGdQg8XeeDrX+Fn/+S3eMPUjdyYgHf+7CdPc+c993PdjbdgnQhUx42D08JCzTfbja6ZFtdin3tfaxSdawW3kaFGkIV3u+IHhVeLoivorlVf3ozxcx5Tb7SS3HPvg7zywvO8+erzSBdtF/++iicJO3hl6sZNi3e2m51TsOdPb7k4Gg8llj65cLfxuXcpNhECXs4xreqOx+oaqMI4iysDZuVCoCkEl652XJ1PSYhdrlb8d1MHFx7euRphdWsdNNMQB8yHM50Qu8isomLqRt4ajRxct2Y3ICr01iR2tn3/SvfufxMUTTQxWsEyzjYEbj6iFkDlgJt5WMegBBw6fJRf/dpvctdd99HLc6/8RJy0drJaoY3+ensfwoeMrnivDjh16hR33PMg33v89/HFkyF+IgTah1/QyvfZMwjmhWStN8DulFS14XfOn+WDLCd3lr+0vMpRJxGuApkg8WUxm+MtamfZv7wPmWdUEtSoRtWw8/Y7yEP7EYfXMMUM7Swiy7EX1nFHFpEfnkVWNeLagzgk6tB+3MoFxOoiohbYi+uMnn6c0egCFfiWzblEJAnZ5nnc499l53vfZePAQaojh1HWUhaT4IUY6CcIuYTs9X2rKHyhRTLfxx4cIF1odG0dZjzi4F33cuK3/h1v2Im3IkLxOA7G4xGPf/ebHD12nN5gSGwK0cxTkKdd89Bxq5xrw+oiaC8XXYO4ubhdXw6fFMQcoGZD9eYDQrjGtRFBKFxzHhfFvbFOwFf/71te5uFHv8xH77/LdLKFMx0vJMhHHQIgRAXsaLjKfG7QlbPXuykR3ejYlXC4vX97quuOFdU8itv1GRBNdx0cDRb1acdVlZKJxGwi1sG0Nx8fxk9CrKmJZGcOhOwkXvob3W00X6EGRrRtrONyFh3/UwTrxdvMLb7UKgLadt+uY0s1CN3uy8mu4ureFz7MmSLYt7TGA48+yuc+/xWWlpbD+xBVbhSw1tqL4iQQHbeh3RbFZffhNzpHkige+vyjvPLKLzjzyTsIaOhZTOVdsDrkGeFgv9YsCIUe9Pjeq6/yPWVxIuEBpfn8cAFbWbTU4ASmrpqyHq0VVVnjhCIREuMM+eljqJU11JFlZJajyhKSHm65h+glqJffhLLEbqwjVxZgKfHZ1nmGmNRUmWT646fYHH2Em19Ezw2QqQ6dZ0AExyM3DmkqZm+9ztAanvnf/584dccdzN17Dwu33Uy+ugLzA1zhUxyYTZBnzyNIERZsqHGTCQx6PY6fOMjcm2+wHtxmiR8jlODFl17glZdf5K577kfo3fImYoKIu8L8N3Mo90zZbou+Mbk7L8VF2Fo8cdNxdCd+t1KMofuwmTmAtn5JOsvNt9zKjbfdyfPP/AjlKqwVRPwyVlJI1daHRos/lr5YYmrL5colGhvRUGjWFVz2WgOP7TlPe82oL7rWoCB6PUmS7ErAvtLxmfyU0W3qmrJdTMjfcGAppOuO2WammoaW0a8WMR9j96B0l7A1JhThtpMphAATJkDIFsSTHQOkA5jHDS0GLAQCjQAVuKGa+w/sA7imnmiQ9bjn7vv50le+xuFrrkEq3eQrNVLcyGjnzne5kkFxx52wGVRBzGrdNZZScOjQIe773MN88/c+prJFi50Jz3FehFbe2gkOC41G8taZj/jvty8yyjPWnOMvLu6nZ0EmflGZsvQ4lRScGa9zaLBIb7GPVNKT9FdjNl54m8G1JebiRXo3HCffv4IyFZzbgp0Z9uA+RJJ4PMjgKUuW+qhijJhbQmydZ7R1HrN/DT0/ROS5z2/K0mCyK6T2C81WlqSsEB+fw1Ejzp/h/O/+Lh9849vkt1zHgc89wL5rr4WBzxIXtgQ7wdWu6dLhkFidcMeD9/O9l19hkudMgCoGGpxAGcuTj32L09ddz8LyCiLWeBF72TXTsWtjiThkkxtoo9KgYzHFOaaxvqMX1b4VrbPgunXe32VRNC+6y/6MymDQH/C5Rz7PO2++xtbFcyBCQKZ1BndZNyLcd6I1Vd1xrzpskXS+113fkdXDJzhbdEgBEEFDu47Et16Bv2HvwdAoWc/N5Zp6yzoUfl/tuHr0LS76zk1nAWXvlo3ECFic1G6jvMjf4kLyY+u+uV0Us81ghomwxjNZxjyhZtBbIzssbhkUT0j0jBZYa4k3Fpczbd91n6UcwvzCR+Ukvkbo1KnTfPUrf5Ibbr0DlSa+fmhPFOPTjl0m+y77Ph67zeUYmfFj6NBSct99D/CLnz/LB2+/gnOOfr/PdDr1lMOAlZKEmkP5IpPa8C8/+pAP8z6ptHwtzbkuy1HOZ5ybqm7aeRvr2C6nZHkORQ2DHiJJUKvLHPy1A2DASdDnt5AbI0yWI9aWEdcdxNkazpyHXgppitAKdWgFd+MBzLtn2f74NXb29dBLC8iFATrtIZMEkSTINIUsw6aJr3Wra5+A9vxLyGuvofenvka+vA9bCSaXtrnw8QUqI1g7dgSRp6gsAZkiXe2jpEqC9tHJA7fdzHVz87xTlTR90Tqb4wfvvsUvnv0pn/viVzyFTBCIRqZoUZ7dVrfbrXzibAoaor/mDF3Lqesidk+w6zu7ZWX3a3tPE1Ww49Sp09xxzwP84LvfwIXO0l03s3vehlbXGB+4CffQ5TSLMrg3Eh5fV0ExK0QTiIqGYHRpBY2ea7yV6BU5AXmWM51NPRWKs957+OMwT0rVMjtGy2QymQSqEu1LFvY84N6Hk0q1RGxRYTjXelSdz3cVU6J16+7J1tT2yY2tJvaZ3m2OBM67eS4oHSAA72GgZJg0Ir4lcc5nCB7Yf5gvfuVrPPjgI/Tm5sPgt9FA3G5LsT1EM1nRLe0+X/vxjsUHl70etjdW9+3j4c9/id/5+B2K6bQBHgn3Ia1lKASHl5b59gvP8VQqcdJxY+n4k/sPkgtFVRbY2qB16ncr4+vJZnXJoaOnGFxzBJIedjr1PElpGjLnFWKxh1uag+VlxKV1+OAjxMI8Is8RaYZLtM/hQlM/civjN97io9kGev8+kmEPkfdRaYZMU+/e9TLIe7g0RQiHsg6nNXLQZ/6uWzn0538TMVgBnXmFUhd+s3Ga6ZlP+OSHT7OwMmCw/xBSapSzHkBWBdnSIrefOsWPf/ELRmnSzIgDqtB55cknHuf6W25j39rBxtnapYB2TWXUWK7Z3GIra9EKQrvp7VVcu4zmrit4uddOvAdEe9nd7waF6eWrl2Tc/+CjvPTCs1w6+wkgw6bKrjKtaCREmYpWk+gI5pWwJNeYcqKxfLr8ZVLJRuk0n9/zVKL58ZbjbDolRgKdEw0179WOq6ssR5MMZXBewwVF5ei2hd6tdcNXPdAmY5bobvPYk7TZ3TVw0WyWnulSyphzEc/vkxmVloFDyVc0NztfkJro70YOPYLb2JjZQuCUb7ynqFmY6/OlX/kqf/c/+y/44le+zmB+3g9sg5n5Ye4qmt0/NJPZKuYQJWzs/t3Rxr0/zaDhO7bcctvtnLrh9saMjgPgG2Aq+g4+2Fjn39YTZlnGnKn4G4ePcizrU5UFrqrp9XtIrRFConsZan7AxemIo3KI2diC8QiR9xBzQ1SaorIctbKEXFlG9nLUzhZ24xKj53+BK3awosZIjasKmJSIqkYfOUr2d/4c5o6bKYY9TL+HTnsk/QHpcJ58fg61MIeam0MNBqRLywxOHGffg7eTLs2hezkyy3znY6WRWqPyISrtI7KM9JqjZKeu4dn/+/+Hd//rf8il3/03TN96BzMpwPrWQCceuY9la8gkSGFDgKLleT/zyUf85IffxzS9BKOL0+7sjQyHxSsas4DW8gpJgd5cdS2Vzp4fIvfQFTbr7rELfG7MjbgOgtwGIbLO05UcPnSQ+x98GK0Svz6lzwHq5hHtOncoQYm4cHyv+7vr5bReicWTIypANtQnkTW1vUZnPewxDNv7D7okKPdu5PxKx2dG39rdpHWcnHM+f0YFQrGQKtBF9712tqGf1Z6ix2hCEkpDlNfGMoCVw+GQ0Y4vrJRKobSmKgPAKQROSp+opbzBnqYpxWzmrQgh0contJV1RRfoaxgwJYBhkGhOnbqZr/z6n+X0DTcHDCsG8YPqda3e7lpAv+xxxd34lziWF+f5whe/xnvvvM54a4O45TnnMMKhhOGpMx9wLh/QH4/5G3Mr3De3QL0zw9WOJM99cbCQWGFwVY0dTRHOYYcpctCDXh/R70OewaCHlYAKKQ4qxUqo64ri7CUG59cR+1dA+5A7IbHOSUmyup9rv/513v2930EqhU6UrwLIvOsmsz7V3BzpkVWyg/tQWGRZoTPflksI2WSwN0hgWJQKycptN7Nw07Xw+08in/gZF7RGnLiW3lceYu6rj7B0003cMjfPhRRm49muMkMnBMZYnv7+97jtjrs4du31PtmwMyWtaEYLPmoEmkREOufshF72emy7Fn5jsez9UEcudrt43Q9d7kGAIFVw730P88pzL/DOOy9DiOg1eWhXOPbiwV15bL2ToNiidYinbfY92nxXHBB7ImeuUT4dZ5bYvKK1qDqfFnzmeri6+xZoSWzYEYK6a27AmhC2lTFdIGQjufgg0odpY++qcIoYOQu4WSshIeNzPBpRVVWTLepM6DUnBVVd7RlgvMJqLEmBcaHoTwRa9FC3Bz46qIF9+/bxla/9Ovc+8DD9/sCD3OEu/SBKGhXfTuGnKJnLhQn2mMW/7BEmUwi47sbT3HXvQzz95DcwdeSYcihrkFbxel1Rzmr+am+BP7lygHp9BykkWZr5fJ7aBBxBkawscGZ7nSzvkR9YY0cLynIT88kI45OyEZkC4UiTlGRhEbm0QOGm7Ew2mTz5A9yJg2TjDeZuuIHe4aOINEMIg5pa5k+dZOHwIZL1LVSiUUp5JT83QJ46Rnb8sOf2Hk+QlzZxieLGX32E13/8HPeZunGrrjR+Ok1Yuu9+Zk88S33+DPMWePlNJq+8zSfffJylv/fXufH2m3nipz8FnYAVaK1RzgVMxbG9s8n3nvgO//5fOUov7zULec/gN7hRY5yyR6c4dtV3NXiUuzzHqfn3p4TA98qFcM0yb0ejq0AAnGRldR8PPPIIn3z8HsV05NeYE4Er/grnFV0Lnl3YD8ETso6GniZNE2azGUpJ6rpq1rMzDhPaxzfgtQNCJ6OY1Ns6B8GYiQXDe/THpx1XVUoqFODGATLGNG25o6/sd5fOjtBxcZzzlKVJmjItZj5xUeJ3qs7gxMF3xERD16SjC6DX6zGdThthELaNrEnpEzyjKe5J8IJd61zIMAftvMjNDzIe/fxXeODzX2F1dX9zn7tT38We37uPyxTTLp20e2HFseh+99OOWBoTlXcvTXngc1/g9Zde5PyZ95tPpc5hqpqpM/xGPsefP3gt6XRCPjePqQ0isDeSatywj1ue55NixBsXLzJN4GfmPGJ+Dvo59BJkJlFCUOxsMrn4EcWZi8j1LdKioLdjWXl9i4XKYf7AUWtNurLK4PMPc+A3vkbv5uswPYWsYfH0jaz/9McsWJBaohaHyJuvRR3cj1USOR7BzghshUh76Cxj/e33cGWF7BnP4rk3jytsiAsnjzBamce8fwFQVKYkFRb36tu8/1/916x9/VeZrwxnlMTiebekVOBq39PPwnM/+xl33fMAt9xxr3fvrmStdKdTdOer3bBE50ONErmKGf3ZdnLYfDtKubOUwukbxwoF3HHn3bz43LO89ItnkcISm2o4R5Pjl+UZVVlS13WzlrvW0nA4ZDKehPyuECCwjul0ihCCoiw8ZKC8hSTw7qCxDqkDbBHWatOJqJPyEl1Pie9wJIS3Qj5rk76qUqpCm+gWsfd+Zmw13YDZjb/qeZAibSvBr5/NZp0IgQ8Ren5u0dLswi4BkcGlA5iGRpfCetDPmrhD1ZjaxCuDkJ51T0rv6yIQWJSENE2547a7+PKv/BrXnDiFSDKau96jNP7w7lZUaHstq/a40kRcKRktbtMCsBiuueYIdz7wMI9/4yx1OcMhSHXCZDTjXqf4awePsq80VCSYKuApecJ2XbIuK9bnNNPFGrd6gE22EJfOom45TT7okff7zM3Po/Oc2XiHjUtnUYMEtTikWtmg3Fhn7rUL9K1EO4sChpUmuzCh+lff4uKPf87gz/06i3/6K7j5ZfKDB1AyxUlQmUbvn/fY3XSG1Aq3vQWjHeRwCIMBJEkQ4BqsIVaGeeG2YSevcbaif2ANc2wN+fonzDanaCEosZTWMtiZMnrtLcbOUTtfF2gCQ6ezFqU1OEdZTHn8u9/i+KnrGPTniJHPPbNyxTkM669rx+36XNfFirIQMcWIu3z6YgwuQ1hH/rNNSj+7VZTnGJufm+fhL36ZDz94j+3Ni1jjmBsMGU8m1MYilKQ2vnHHXhgmXnI8Gu9KYvZrqo0y++8EkFu2nokU0O/1mE4nEeS4zM3t1tz5cYsZneLTlkhzfGbft67JlyRJ5514tNEl54IsWYfT0nOpxN2m8fn8Y4hQR+FC6yBv2oWMXLx5KIT0qexhYkQ4lw2cwF0XzuDwPHsO4SxJuGetFEevOc7X/sSvc+vtd5MkviW1cHuAhfg0v6RC2q282nv8wxzdbzT7YFTKeOAwVZL7Hvgcr73wMz549zWUEqwmOfvsFn9p7TirlaUWChJJWRWcq7Y515dMTqwijxxDLQzBtwBg+823mb/xWpJMs7w4z74DayyvHiBbXGI2HfH2y46zsx2SrIfpTUh3cnqbNUkNTijSJIfaUFkDwpJd2oZ//Ht89OpLHPov/lOSo4dQK8sw2vKUFUmo8RN4cHzs69fsnAgtnLw162wFtg7qKFapW7A1mAJRV2SLK6jDB5kUPyUxFUIqxtUMlET1h7xTTlnvBQ4sfGazCXIXy40kgrdef42Xnn+G+x78oseyXCtLQQIum8fugt4dsfo0d751/7rYUPd3e46ONMQkQ7sbR2p8lfBVGXCb6268hVtvv4sf/+C74GA0GTeuUy/Pmc2mgVFDtroo4r17dK+3lGz3hWgb4r2ukGwRjI3pZNIoo134UffZRJvA6Zxo3EX5GfG1q77b5TNqhq5jAkq5OyKFcz7krmIINTx5HABPcuMvKzVEpSMCR0vwc2PCYbyWNaZhk/RV8l5pmUBb4kJvq9hV3bnYGdfxq1/9On/37/+vueuez5EkaStuV9wlowm8+3k/ExOK/nO0dK7wvV3W2BWv3JnQ8DuoZw7sX+W+h75Img2w1pBsTfiVpTWuGfQYS8Pb1RY/mH3C4ws7vHT/ISYP3Yw+fQ2i36euSsrphOloh2o0wQBbFy9y6dw5ysnU93tPNP1ezjWnjqGk3zEVlvzihP6FAiH8fJjaM4YqIdEoXG1JlML88Hm2n/4pie6zePdd1Pi8NCGkz5itZojx2FPbLi0g5xeQOmk3Beu8Auq4KM4YqGeIugRXoVKNPbDCJ5MJU2fYrmcUGOpcc2lhwLfHE0akKBUJ91vLozY11nlesKquefKx77K1cSFYpntS+USrlvzm5RfVFVkYOzJytb/j2fw9xVltZSTKq9sVvnKNFeIaJ9HLdIQ4+mnG/Z97lJW1wz64E+AQ4WC8M8JUFoyAGp8f5CmNwjg7L2BXwj1d15AQ4cq2U+BOiKz7qt2WtG03XuRwCC2xOqzRRvCvvp6urrJCyyLbWWBdU7CNuIWeZ6H0Vki/0UVCqSbRygqoBSIg+jamuzk8f68JfqkUvk6sNiEZUiCQ+EhYJ4NVeoJzg8VIh1OtRMXK/CzPGc7P+2yjDuDnhUGwi+ALEGJPFLEDELbyslcI258rvR+PuHs0P1f+UCso4SUlJHfcdS8nTl5H5gSn84x9WvP87CI/PdnjrYdPMP6VO0kfuJ3BwUOorO+bBgpBVRmK6QwznYI1XHvdCW69/SZWVpZ8LpNznr0hWJXWVhhToGuDfHedtFbIfOg3EefaDntSYaxlNh2RlY76vY9gWjK85jj6wAHQCaauYGsbzl/AfXIOygrR70GW4aTqDFjD/UBYEQjnrSRnpjjpPLPCwpCxhIm1bNvKU7vMz/GEsrzV61EZy6y0WKfCnLaJvP4yfnl/8P77PPMHP8bWNSKGvEMLohj6voonfsXjsvSOMN+tLLXnc8JDDU54dgUb/u2CmSOE2FXv21rR8X1/z8JZjh73lMpaZ61ya2RbXCaTYRX79dQWXYTyLRfoh/29G9em13gak6Ae5a4Silauw7kbjMx5KMc22pBPNQa6x9WVkjGBWdJ1tGF8QNFJ2PIXUtKRKF9VpIJb5hWSCMWU3lz3u5EL+SQ+GVJEZzUCY86GtkK2k4fhdq1lJWQY3tAt1AXtHM7llOCJJx7j3JkPkbiO2Rh3h5a/IJhcn2p2d5+763N/KkgajW63V7r3SHzzZ0ezxfnzJ0A6WF2c58HPf4V+PqQuZry5rNn+/B3om64jP3CAfDCPTBIv6NIzCQjpUyTyLGdfbwCTgtOP3M3+wwe47pab2X/0aNi4/JjNZiXFrPQdaj7aYGED9NIKLvPRKiUkiUpIdUaa5egkRWiBdoLxK69SbF1EiITs1AnMeIK6uAEfnYX3P8acOYvd2kHUBltXUBsO334jUkmmlzabsWjux9ZQT6GeIpzFWYMJvFYFljpJKReX+PFwwPd7PWZEq1v6xdTZJbTWbQTMOZyr+cFTj3PuzMfNs3fn+oo5ZL/EsXcDu9r321yprsPYfjdGu2Mijsdfd5/fOkGiFffe9wBL+494hWSjQHnjQCkZaG/jEIfnqkPJjYv32d6/b1zhvGIRIW6E9AGq+EJcMh3PqWsExW69zohAChi0RPzcVY7PcO5koynbwZCNpo4L1CtKiZaK+WGPmM3puamFf5CojGLEzblAg+J/pEzCOSVYUFKTqATlZMMW6XMyvBJpMruDeS0M3jyNfEbecGN94xJPPv5tbF03mFdkfPSbaFdpeBWHk0GZyl1CIEJHNFyXd6creN6qc6LxpMP7HUvKEXhrREcvdQU0TGZ3HoIlcfPNN3Pitnu4eGCJ/p03I4dDRJKiE4lUQXCiYAnlyw9rD/RneRY6ECdsb2xy4ew5lErJkhTKEoGlKmvMrECNZ+h3dugnA+x0ip2MUDpBpBk2SZgpR2FrSiyVBKsE/MHLvPmf/C/58H/7f6B87UPfyWJjRH1xg3Jzi2pWYpCe46iqcNWMbNBjcnGdzQ8+8uMhRDv21iDqyisRAdQl0zOfoHCoJMHuP8q7t9/GNxcSNtO8yY1x0dKQNDWb7cYZE1oFFy+c50fff5xpOf1lsFc/Px1L+4pHVGRcfr7mu53NznY/t3ffChIUzI1w7o76isEl51hdXeO+Bx5BJ2ngJ+9CJ47YPj7mCREQlAY3crHawiukLM+abtjSOYSTnrCQvc/ubzTLsnC/wdB3+O9EV9UKz8cmHFLscZevcFxdKYlQta9cR4nvthK6u0ttYDytvLUivUvn3fZ2xGXAN+MkpVna8BJJFNJJnMErMxS+8iamB/hBa8ckAGjWg5haSBSi7SkXzN2nf/Qj3nn7dXYBeXSiiJ0dqqtghOi6dx03IGwWXu9F01UEoqx2l4vXj1ZYK3jBXYz3v0uCI+AY7082m8NwMMfdDz7EqTtuR/YylNKhztHXgamGWN6ysDSPTjSmrFDA7PwGx+6+nQM33ITOF7l0cZN3Xn+dnY0NXDHFmgJnCmw5Qr5zlrkzM6rNDVRZk2R9RH9IlSfUmcRkmvFAs51L1rXlfA92FjLk9oSNt19l/fXnKFzFSBhm1lFYKJVmhqM0NaYqkcZCyOS3gefVj723inAWZ+tgKUiMLZm8+x5a9RjdcQ+L/83/GfW/+PuYgyd9G2nw3OBBqIUj5McIXB35rsKm4fwm+pM/+AEfvPNOUz3fhSh+2TSO7rFLGcUNuHOOZr24Rgp241fBdY0Y0pWueyULTknJvffex4lTNyG1DjcifCmOiWezOGEwAY4xQclFCMPrbUFlDEVVdjLBvauW9rIg962lE63Pxk3F7coOD8PQcLAJB6dPXsvK8uCq43j1gtxO77oY+fKRiphYGC/r/22Foygr/7CYgBfJpvg1TkWrDDwRFJKmE60xpqHr2GUvBEsjYlkALiTdRU1PqIT3JHQWZwVCaGaTgu9++1scPnaCXt7vGsn+J7p9nYmPg32ZYIRIjv9g++yONmIGLXwqGsXUWnXs0UMivicio4FtDHfXHWNrOXrkAOKjFVy1hVKSJFGByaEmwHpoLbn5lut4+YVfMLpoWN2/xuYbH5MMB6QrqxyYW2T18BE2L5xna2sd6inzywOksqjNEe4XZ9DbhnrhANXJG6muOYLr5xRvvUbx3ktcnGxQnD5IJRzF+jZ14duH5/0Ba6uriGPLFDjy2pCAz+BGYcYj0p0MoTUyTTy26HwkNmKS0fXwO5PzQRMH5XjE6IJh7d/7K+z7m/8+1ep+DlY1t937EE995/eobO1ddic9OZ812IBdetkVzb/Bh6x3dsY8+d1vcujoMQaDuUaJfKYS+kwXJEjvp7hvl1lajo7bLloIYtfnu+st3GNIXhTAyvIKn//ir/HBu29RjMbYsOYEhIikAKGIxpfHaL1V3qztsFfGsi/hCPTPIiRRBtUpOopHCkbTSVO0q8Ru63RXNFlIPv74DFWgn/m04+rJk0KFAWqzm1tQ24+ma0xARZanFLMCnAvJWgSO3sv9dvCKqCoqhIBEqdDL0LsqUrRp+u3u4ydHCp+D4ZxPkGvMyjC5dVFhhUAJ7fEIHM//4nneeOVFbr3r3gZg94PV9eS7Krar7LpRyLCLyRjJiLuE7+YbhYRAURr9ctfcfzh3C68F3qV4Pw4bBNOzZIayD+FVey/NyNMcZXfQ2jcZwPj7zLIMLQWiqnBY9u1boZ5M2beyzIYx5MvLyN4CrucQScayhHx7g4sfvk0vP4KsLdVrZ9Bmkeo3vsDyX/izZKdOU/UzNILxT3/GhX/43/LOhQ3y4/OUlcGlDjHN6CUppj/HZG7IplDkwvMa5RikUr60aDTFZBNEr4/Mi0Cx7MDUYEqcqRBCh1SA0u+KIgNTUM1KTv6dv0967Y0Uoe4rSRLu/dyDvPzyc5z94F2ElNS1bVxl63wZk1QqACMC5T3Dxit66cVf8Norv+Cuuz9HDIR0w/xXCvm7K70uunLjXfTGa2w+InafJAibCzuS6L7Xvd4V8vj25gUJHLffcivP3X4vz/34+8GiEcECDWCCg7hdugiBhGJ28E22nRMo5/HXeF/OSWzdrnVMgGyUxIpA92PbpgPRFY9bjLRxLATTWYXb83x7j8/gU+oon86ZGuIn0Y6hczCb+rbJQkpqGyv3w27fUUy7s6FDK+qOJeTc5YTn3ehBRPNNANy0VC2Y57oRM/++E46ymvHNb/4+J6+7gd7cQqNwLILOV8MEd24v2FB7AbropjWCSGcvc60ABsO5UUhREcULRSK4Npvb4yJdOopokAkExXgEVYkS0MsScF6B9+ZyhsMeOlFMtrc59/EZLl7cwFjBzuYOb/3wGf7U//X/6MPOSe43mqogNzVZPmA22ma8voM4eD8H/uafZnjn3Zg0YRbG3jjB3J13cvahLyGeOEvam8OpCa6XY6UEmSCzDD0cUDjPTyWEw6J9ESc+o7gcjXA7GUK39DZUJZRTRF4iVIKzBmuNHzLrsJRYOUSePkbhdFD6fhwPHzrE/Q88xO+f+QhTFl7Z2N1FzLXx8pskvvykMIV/TUJZlTz5jW9w7cnrWFle2427uFYGugqhAXdFnJzwqe6GS5zyjgw3dm9n4YSPxHygeM+t2d6ewhFf77hHzX05er2cR77wZd5+/VU21y80tEEEBez3yFgOZptT+9t2ATeKCixE3oLSjJBf9CokAowNpS2icUvjOhAi0ggFa02IJor/WbmAV8WUnIvhx1iIJ9A68VhGwG283ISlGxaOtaFHlAAn9vBXu7Ybrg3C5xze3epMevd3XHjRVfMa3KETFTSya3pgRSDTl7wZpHT0ehlSSN55+x1+9sxPfN/6qCTCDhHw746bGc4nQo4Grk0EdV3sqH3+OBlO+BwvE87nOvftCBXfQbb2VlZ3ffb4WjCEcc6xs36BxJXsX13i1MljXHfyKIcPLbOyPCRRArAM+n12NnfY3hxTGe9CO2uRxuC2t3HjHXAGlSWoNCVbHDArLXL1Rm74B/+AwQP3UaU63LmPWzoBQicc/JNfZWP5GlyWIJMeIslRSY6QCXkvRyW+JxxJgk1TCqUphKQwlpm1TIoZmxubbG5uMZ1NSQd9ZusbiLpEmBJnCp8w6SpwBuwUV9aMygRnUx9h7bTVUlJyxz33c82J6xuLNY6hC63AYluhqqqZFQW1NX5jcxZjDe+8+zYv/OwZyrryln04T8zLaXVFu6k2Uazodu0lNSJax+1PnMtdLp2glcXmeq655zZZIlwz/G3Dxh0xnJgDdfL09dxx34PeKnTOc2QZ6ysoHJ1AT4hkx/bo0dMwDmvic7UYnHOWLNH0stSn8Ni4zlwbabMElyLoi9BcoFFsfvA+tXA4HldVSlIEkjUnUDrBOUFdmzjcGGOxxoWkR18mYDtJcM7F7iB214S2uSPez4y5QbAnr6Tjk8cQr18i1mNVToUWTjE/oxUHn3IgqWrLbFr4YsLa8J1v/Ts2Ny7spsp2XUzDNv8ZTABhiRqjsWhwFtsYqK2iamR0j6zusrTi9mTbaGK4bQ/UN5ZWjLD4ua7LGZP1S+SJY9/yAr1U0cs1/X6OThJqUzMdz7BCM5xf4OiJ4ywsLbBkX+XRL80YzvsOuaIuYDbybbw11LVl5jLKpeNU+SJ1iIBZITDCEjEU6yzzRw+RnLoJK6VnachykqRHluckaQ+pfDImSoFMsTrFJhqjFIW1TKqarZ0RFy9cZDKdcuCW07zxxNO4qsbVBVSFd93CJmerimJmGdHzuWcCD2jHBewcKyv7ePChR0nzYRNIiZuYp3oRzd/GRPZJPzHWQYXj+09+l0vnzwQR2F1cS5yuuDHFWXeO0M6UbhDl8jSS3bLcbKR0S7K69k9nE3MxersnTeFKbqU15Erz0COPcuDAYYR0gajNu7EuKBBnLJggoNY2+YPSthz60QX21pX3JhYXBuSZD67IYLHFErHQAohmUG0rN1F29oLgn3ZcVSkJ8PQjzjUtlqJr1WhoFyv+baCYDcpFRC3rZ/EyBROvIXYroXjYTkRkN2AY/FMnwiDboOhiEuflQhDv3VrL2TMf8/QPvu/ZD2mVwq7v0lEgXVPZnzi8KjoWEM0sdjbGyw/ndvPu4K7wfBFnavdH8MRo4+0N3OgSvcSjAaPxiOnMU+amWUaaZfT6A/LBgOW1fVx38/Xce9sKx6vf5u57d9g3+X0vKMZiqzpgKJLaWOreAUrlO4zIcC/Nc4jOXOmMhWPHKF2KyjQiUQit0FmKSlNEohGJRvdzhgeWOXDjCVZOnyDZv49ZmlApydTUbOzs8MknZxjtjKiKAjsbQzmFuvA5SjisrRBVwajMqciaWYmCHv8tMdx06x2cvul2BJBmnkyOxsoN4WgVutaETaG1uBznz5/jpz/5AVU1xeKjU12ajjYpsSsdXR+rPT4z2Ra363f8jOusqfatvdf6lKOz6R06fJT7PvcF8rSHw/rIlxChsh8fEIhjENYQuIYtoNkzrfVMIOF+zl+4xPrWth/REJywxlFXpm02gE/fia6bC8pJ7klKvtpxdUtJSZ94Fk7UajrRuHZCyKaLhE/ucjhnQndbEN5Kvuwc8caanm/hiFS7e3eG9jshq9vR1AjF83YneNdzNH3WvFv3w6ee5MyZD7AhvBh3ufbe9qqWPcLjuoJyFQFsJr1d5NHsJ25UwcXzv2ldyWCZOS8dWGfYPH+WxPqyj+l0TDUrqUPRNA5fvZ2kJHmGMTXbl9aZzargggNCgSkRIQdI4KlSa/pUC0ephW5Gw15BeOKzn7zjNmq9gExSfCtmicyS0F7bcyPNL8+z7+h+9h8/zMFT17J2/Bi6l1PhfBt4V7MzGTOZTphMRow3N3CFV7BOKBAJGMe00KzbAVZ0CPv23psQLMzP89DDn2ewuEJVVxjnxyyWmNiQniIC86gT0a32PQ3r2vDMj5/m7Efve1kKiYLO+h+cDL/9v3fVXOw5rrbodrlFNm7a8Vx0ZKPjN9L5TOfaXpfIcG/+5dpZtJDc8+BDHLrmlC+mDxIc4RYZ8UtnwuvQcMbbNiu8re+zHqczEqxEONl8VjqJFqqxyAjX6W7S3THpekKfdlz1E1VVUQRyta4gxGZ+Ig5Y+NE6RUpIEhUuHl229qb2ZkN3lUr3tbgf7lVK3c/tNXejBQfs+nd73+CcYGN9gycf+zZVWfk8I+ff7TYjbM3m7t8dxRf/68jlXivNdSZGRH/bE/F2cAIZom2E1JJAntaJcCJgPNpidvYDElNhbM1sVjScRdbBtKjYGXuiu6WlJRZXVpBJys50nm999wBbq3+R6sTf8FaIqaAqcdWMqp7x+kcXGMuM2jmMxZeoEBcO7Y8D4yRHr7+B1evuweghWueoVCO0wqWCWhjqumTj4kWq6Ywkz8gWF1g+doTh0hImFF8bfKdVay0S6ZtjJhlC5aA0DsVsarhQ9ilF3mwWrqMMWszRL4hT113HLbffF7ySaAFEtwWqug5pAjJOucePHFS14cKFCzz1+GPUs1mDTzXz6f9BNGI6hjsxzSVQue/6HVGBiOU0OUGd79uohPa47C6okFZhRelrE3QdEQ/1chwVwuraGvc+8gWyrN+mxcVNsqMYIdSQhjN576j1bnBtm2/hu2G2MEaU445uiDmCMVG0ax3FH6U6uYZXOK6qlEwIz+/V/JHGNoJt0XKpaxNA7vazrrOztQpn9wJuJj7MVjQN43evdMTUhCv1qIrKqNs6xloPaiJ8d5Wnn/4h773zRrBiQqb2FX/avKq4EFqnqqu84vvsGrNuCn4UZl8+0xkbgr3W3SWFAGd9i++q4uLbbyKnmyAqiqJiZzTzC9sZZnXN+fVNRpOCWVExnZVkvT55r8eb33qK5OjDuOv/KpWa8xEqW+HMDDMb89pLL/JPf+ff8P577+OiFeqTpXb9dJ8Rqbn5gS+hl07hUoFLFCKVCCU8EV9VMp5OubS+wXQyBSzp/BxHbryewfIyKumFZqXe1M+ylKzXQyS+KYGVCiEc4zpnRy1gnOyu4V1y4cfPy2mvn/HA5x5heWU/0hlssG5ssEi6nWx9smU7704InBT87Nmf8vYbr2HqvZnHuy3g9ggLOJxbRJy0ce/D5uP2fK05VbO9BQtEYomhddo2XVfY8Hb/BzGtwOGQ1nDvnfdw7Y23+G3QgUI1dL0iJFf6DPqgVIOQ7qrZA19kITzBW1x30S2LDkg34bQxIAKkwx6jouvVXOn4DFvKehOv40/vxZPiTUAkL5dUlfEKQHqyL6HEHovInxPhUKkC6c3pJNOgBLWtGoReCOE7YHC5S/HpWbftAO8dCBM6msyKGd/51r+jGI8bi6jlimqFqMGMwnkbIex83rOweOvCxvfi37sW+Kcf7Vh2ry9w1nLu/bfozTY4fmCJxeEwTLIlzzLyPCXRivFohMPn7pjaeJdkNOGdp37Crb/5NXSisdZRV1NcNaWcjXjt1Vf5J//im3xwcZvHH/u3zKbjxkL7dBfEbwDJYIEDN9yDy5dC8EiD9LV3qAQrNduTKRcuXGK2PcJOpqzs38ddn3+Ya66/gX5/Dmk8BGBqE3Z+61MDjKcxMapPJUOLJjrGhXOtFdJ1aYzl+PFruPf+Rz0jhAtuWqidc81iEBC6PxtjAoZkqUzNZDrlice/w3i83Ww68eIxmtqds72uZDOP0FrAXX0GTbF4LHhtwiUdjy0a1gYaS6Uj+UQrqfvDrvctc3NDHvr8l+nPLaK1RCrR4kt0LyBa+qrwjwiOCyHIsrxda52AVAwyCdp1VtW1b+m057662etX1M6d4zMdvGi9AI1Jxq4BdPgMZD+0ppOs5f3ZjvJC+DR34zChfbQxdbBeKpy0pIkmUToU9IbvSd+TLSL4e129PM9bAekIqwfe9zxQg+LBSy++wCsvP4d1JohJeKvrIjYnaE1oB3uqyeNF48f88AfvgJjnZJsoX3tT1vkgQnuKMNZIoGbrk/fIdj7h5muXOHl8jTvvuIF77r6Fk8cPM9/vsTw/x5GD+zmwb4lBrpkf9hn0eyQ64dX/8bsMD6zS37eMc45iNmFne4PR5nnefvct/tnvfouffLDN2ClefO553nz5xY6oX3nREfwN62D/yeth8SgqjdE2hQwNCGSaUSP55Ox5Pv7gY6qdMUxmZFJw6vpTLK4sIYVg6brjfPzi60zHBW42xe2s46aboaFp3PmtD+gE6zwObHytfUmSas099z/M/iOnSFSIICsVdvSO1VEH3Cgk7HqbWKGE4vVXX+HF53+GMTWuMx4xL22vTFxxzYSFfdknggDZKIrhNNF1d01Lno6iEq2SamZijyaKEEksDwmsS9xy483cctu9HldVImBtIZdPCRCtpdncX3eNWUs9Kzy1cufoWjvdHC4RLE4nRXO/7XppndSrHVdVSjpNUFoFF94RmkAF/9Knm1tnMBhqV1O5mtrVGOH5pItZRVWapnLZOh9ij3ihsQZTxhQCRzEtAvF/TLbzMyaN9aHyjo/aHYydnZ0WP2qdodbU7C4u5/uhOeuoypInHvs2O9tbfi5M7cnf4iD6qzTWUpsL1ZnAruUGHZ+9g2tFM3iPmezNfhsszLDbOK/YrSkpL55lML3I4cWcRHghn5/rs7w4oN9P/aKxkKYZJ0+d4MSxIywtL9IbDplc2uKl3/82d/6lP4Wjop6NKSbb1LMJpbNs7Yx558KIqnY4Y6mqiqe+91gzFruUUbvFYQMdqnOOPM3IF1cRqo9WGpVoZKJ908o0xSKYjmdcuHCJ7c0N6ukUVxTMRltMRyOU1izevcMN/9WIqvcOtigRziDq2qcrCNEMb+wH2NZQ+wkxtc/sb4BrLPv3r/LA5x4lzQehBs4Xh+/i5A5gNoimY09Vegx1Wsx47LvfYn39Ao2XE1Na9oxNd6yifMWb7tjxu+UmAgDOeovEOw2XKxp8NrQvirX+d2ODeSdPWOddfBsF1OCcCWvNU+I+8oUvMb+4D1N2rcX2/na7hCHg4lzDttDmONkmxy4q5zaIFK0lQ2yNthfU7hYjX+24qlIqqsIXUDqLVWCVwykL2v8ICTJRyET5XKRQWOuwvgwkphO4mM1RI5TFz0JQys1O5zlmkL6HmRXRU/ZV7tHAaSyV7k8TJXAhFBwyVne5XpdPAA7eeuMtnvnJj7DGUhnTmOi18y5ocxeNpRMnz3M5OVor0TnbAfWt7wbqdhn8NFIXAe2grCF+V8KsQm6dY6G4xFrPsG8+Q2HRicRhwBrfHh1HXdUYW5PmKSv7D9BfWUMP53jp33yLpWOHWL3+OJPRJrPpCOk8Xe78gUOc3xrz0ebUK19rKeqKl19+kZ8/+xOsrRsrswFHA2YScUTn/CaldYZOcpIs95E3rRCZ72SS5Tm9QZ8kTaitpShLrLVcOneR7e0ReqXm0H/wU679jyeMTv8jnBvjqhrK2kfiiBt3gA6Madz6OLc+V87n3cQCXCUEd9x9D0dP3uQ3N3zPO62VLwaXMWWlhSQgwgGS2hk+fP9dfvqj71OWZbB0d+Mge8HbFkdpt8W97zUL0oI0fpm2C/ZK5/TvRQmKuXXt+x4GiQrOWdt+xnol4Kzl2PHj3HHfIwihG8XZbobtfcVCXeNcCOp5bLMByWlTI+iMXV3XRK9FEHLCQj5U81xBuTfW7lWOq5aZ1Bg/XMFScjZ0xVUGrCeBkjpDacl4WpAI40GzkEglpMI6g9Y6nsLXjAkQTlJXDmP8ADnhC0lFIklEip0V1KVpKBCcCyZ8q96RgE4UwhlPbRJdxWjJxfqMIJCRz9s5hyCQnduKb/+738eWE4RS6DRDSD95SirfX4vWAiO4Y7GDi5Iy7OBy17WlkpRVRZKmCEKfOkfjJgolKcqSNM3QylNDOCEYJopj8zmLakqSzEiThDzTKCQ61z4D3lgSpUlT3/rGGON74Q3mEMN5dj4+wwu/9w0e+s/+QybTMc5W1HWFsIbF+RUMgp+9/AYTIz3oGTmIbM0T3/0mh48cZGFh1S/SIEgI0dToGWvQQiGlod5eJ6dC6B4oH0kUQpKmKYNB30daBGxsbTEtCrTWfPzJuZAFXlFPLXoehEuQSIQ1AYhPmUwMhU2wQoXcGOOjdCHDPFrCs3JKkqQNXCCEZDA3z82338k7b76EKUxjmXtxjlZPcCmEr7HUOrSJtw6H4QdPPs6tt93OoWPHAU/EZpxrqkBEwzggiIEpF87rGlel66z4xWhNqFAI2dRxsxW4tnRJ+GcxQd464hc+EOpRhQ3VAYFNwcW8wdZV1Vpz/0Of5/mf/4zzH7/TpEg0EEmDF4X7j18VMfXHNWk/vnDe0XgQIkbQvcISQkATfPL362mJZTMun3VcVSkluaAqAw+REOhMIITBWOfBa2OoKZgfzrO5UWKl8wWyKgEnUFp58jXlLRgpHDrzCkY4MIUBITCB7L+uK6bTMUJCXZfUtvJUJUJ6PC52KYGGykRrSW06maWi+8uCBKEFKpe4kuAvO+rai5AQgguXLvJb/+q3UKnE1BXCgU4SH8o1bWQDG1gN8FQhEuFpW8OgO2fQuUZIgalr32ooUZRFhRIJmOCuitCXDUeaJVjr0DqhB/ylr32J/NQRagVCOhKpkUKTKE/fUpUlrjZkSYrKU2Ti0/4RGpfnICQv/Pbvs3jsIIOj+9i8dJ7ZdBtnLav7VukvL/H6a6/xwlvnELVs0w+cd8s++ehD/h//8L8hSVSQaYtAIrRnioxAqa0sy4njC8dXyDOf75QoidIK4yzT2RQnLPNzC+S9Pg7vIm5tbTKeThFS8OZ//xQffmPAI//w68zXX8NIidKGajyhyCp+91/8K579cJs6AJhC2KB0NEK4aFijpGgsKp8t7V2H8WTsgX1rMcJ35RBSBm4tFz4X1IaU1MYEcNdb/pc2L/BP/8k/Ym3tEFrGPDy/4SSJoiwrqsqRpYmvAZO+AiJa/ZG6p6lWUIJEa2oXa0djgmHI8wubk1QxpcaEzwUoQ0a21zbsHtEwnF9fkTnS4lBKBs/CYp1EJ35lOClwVnrLJaRkiKCQnbU4QyiuDfiThDTTlFXtIRv8Btslj4tZPD7PybQLUbZ1gt5Cco0190dSSkJWpLkv4kY6pPaWST3x+T01JUppxuUWInWohFDPZsnTjDSFYlZjlUMngkQCqkKhEQbcuPYWBgZJ4iMS+PwbpwTUAisdOldU0zpUzQc3R/jylWlZoxOJKWpvumsdQHiDsXUgNpOoLMMIkE4ijKNypc+7iEljImp6b8pVwoEKO2lIGahNja28DCjhdyRrXEAtrQcSa4OUClM5lK1IE4HqSaRzlDNHZcA5g8pNw8nkhMCUBV95+EFOHVxhZ3ODOtX0c0me9cEakApb19iqxhhLPsiQeR/SHkIqnEwQWY/RmYu8+Du/z1f+wd9GaIfAsL25Tq41CyvXY5zgm499n42ipta+LtHUJswD1NYymoyR2hNzOQdSadDCByUALQSuLji6ug+tSqRMkNKFLjIhD8nWTKY1SZoyWFhAJZLpaMTOzg4IOP/zl9h68z2u/dJfQL73MOOsh+hvM1iYp9aCN19+iSee/TlnJzXOkzyTSN1gGhaLVAJnTZu9bSRKaJwlzL3Ft2QHrXu+Q050PZ1BS0WSalCSWVF4NxHQ2qEzhdSCd95/k7fefgspPXOqNYZES7JBQlFWVDNLohMcvo5TC40QiqKuAyVPKMtyIclU+Y47bdpFsHmcL50ibrxaBBjC73k60egkCXz1NbWpfKGzU5Qz3wsRBbaugkKTEdvA2RpQ9AdD78oqCdIGaMHDCFL7zUaGnC6cRUnpmS+EB8g9WUjMWwrdiJwM2BIN/VC8ZwitmRQB6vD/dZXZH1op6UyitaAoDWmiKKoptVEISnrDPrLWfqC1Y7CSUUyqwAhpGOzrIaRlslFSO1CJZjCXMp1NkFJSFzUqB0ONoEYoQSIlKIvKNM5MUQJQkM3nkAjMzGEqz5NUmxqpBTIBqxQ60dSVwWmvFFXizWhT1zglEIkhyzST7QlJpkiVQAtFWdXg/LM6ACuQ2uG08xOfaarZzEdmcoMxIJRGJKHQOGArQgpULsh6CbYKcKGw3krreSJ+nUlmymO4MivBSpCKfq/HTWvHueX4Yd/1w1ahQUKGkhqlNEjvNrkIuioBaQ5zK9gk9WCnqXj+X/wOK8cPcvSuG6jrKVWxyNLyPJnOyVeW+ckzz/Ldn7/G2PqdH+0BTBl7/MnY56sMwqNQPR8yNnWwAHuK+VRw69FlerpA6RypE18fGXbquHWOJxPUxjqDYZ/pbEZtLevPvcIHv/sdbvgrv8Hh++7ylrCtmRZTEtPnwvoF/p//8rc5V4YokPTpyqX12eueXLSln7G1IUk1xlXoTFMbQ6K85eM1mA0KKpadONCCWjiMrZoIHCJm13v3M+unVKaidsYHeEJJUy0d1tTBZRFUxgYrTHuWAxxVWSOF7xZMyBq3EoRy2LphOvLJr9ZbNXXgqBfShbZlobu0sFTOgjMorVq3UPmkUzcrgxHho9TeLbWhZMTzlVvn2BltkvVznJAhp9DDJkoKhDRIDcpZKmtwtcQJ3wIrzTNMXeI50jzFblFUJEGRWeMCrhsL8W1Aq2MlAUgFdVWDlL4T8x9VKWVDDaImy2E436dYnyAc5Jki6ys0gUzN+KaT/b4/XV1X6J5DJ9CvNdNJRT7U6BwyKcnmBfXMInRNUXgeFqUItLgKKSAxoPveksnmBLqf4CoopiXFqKYqKgYLfVQqqU2FlDXK1OS9DFuDSCRSJ5TjEmEdMgelHZmryVLhP6MEulIU04K83/NCLARploCCqnIkmYQd43VAmjBOS5A1aRqoT4ygrGqSTDNY7LG4PIAaNje2mRUVaR9qYciyPqlWzDvF5oa30rJEY8uSoysHuPfmm3zbKSMQ0oOY4MfGWYvtNN3MshQhE09BMlzz/vpsh9GH7/HSv/zXfPW//I9QrkKlCb08Y7A4j+wt8u57b/H/fezbjFKLblweD3hmPYXOvPXZH/aZ7MxQTlMby2AppxyX7JgZQjiWegmPXneafalC6xyp8fOm9a5W7i5EX6azCUU5o65rxmcv8tG3v8/SnTexfMeNpGmGc4aqNigs65cu8f/+5/+cl87vYB2onkIqsLWlqnzqRKIlvTxlVtRIGQjulXc9KjPzvOG5CtXx3tCsyqlvQZ1ISBXSCmxZe2xQCYTG5+zgPYJJMWZqRkgt0AKkcNSVd5ZUqkBUwQr3ik2nmkG/hxDaL1pT4oxFh64txgqcVMjEeAjAekLCJkCkfdGrFSEUp8BUFpUkPiIsQGqBcxU6lWhk477qoafuMaZGOtBKhuCA3xir0gHSK2YKr9BVBdKilEArj9GhHa5yqAwqV3uaYyWY1SOkANWzmLKmrg1OOGQqsNSgJKYKYycESEPWT6gqS+wiIiTYqkIJTZKmfwyl1Ev8LqCBtCTPvCOTZXMM+vMU9Qxja8bbU3CW3nwfpRKcqxHCkmea2XSGtYLenMaKiuEwY3FfyvaWoS79zQopPIYD9HoprobKOpIcsqyP1pJM+9ob3RekPRgYRZr73Iu0P0dRlMwqQX+Y4erK+7LakvQkorYMBh57ckKyuNKnmM5IkpyqqBlPLEkCC/2hB0MBhMG4hKqqWBoMsM773jJPqU2JTmUw9TVzIkFIwWBOk+U1hw6s4upFtkcTJsWEYlaiVIoxhv0HDnOgsJz95GOyLCNFc8eRE/SUwNYVRoBOQmfhJPGuLIAFJRPviioN2QDyBZzOA4BoeP63/jUrxw9wzd03ILKkjVZlfS7trPNPvvV7vO8m9FYDqIzAGcdsBlCRD3OSFISs0fMZ1iqKmUWnPs2jh4Ki5u5rD3OklyHrAqUSdJIgpMcNnfA7dqyDApokxWJzmzf/u98mnRtw41/+0/Tnhgjh3R9wyEzzP/74ezxz4WNEJuj1JMOlHlIoTGG4dHaEkgm9vkKlhmo8I9EJmZAYZzEzRy9TqFSiMkVfaIqiAgeznQIqjwnmg9TnaY5KZKbpDVOKyQxq4YkTcoPSjsXFeXZGOyQu5mf7TYgQCZ2MC4Tw8T09lOTzAlsbjp84TP3ahPG4QCiDSiXaCFxdIxMX3DrA1VQF6DQFaRHKIJ0PJjlrUdKRDaAofTJiOtQY41DCkebap9QYS54qrKuhsD6FxxiSVJBKX2WBMtS1TyUjASENOmCkTlpUKrCuRio/PjpLkH2BdQYhJHVZAgKZOySGwlh0T6N6MuBHzq/l0iGs8M/bAycMeV9Q15bV1VW2d8YUddUGq/4oSmlhQbP/wEHObJyhNAUra0PqqmZl3zyL84tsbW8yns4oS0Ga9NC5RmvByuKAfg6D3jzvJ4bxtGRlrUdpHUvLQ6z1wrV1cYxKFVlPkWagUsHCQsrmpTHL/YTeMEOKBFtbTp06yZvvvkdZKpI0Ic0UaZ4wnRQc3LeEMYbzW+ssLGZII9h/aB/GGc6fu0SqNItzixiT8N5HHzK3olmWQ1bmV9nc2ubitiNRKVmuUTolzzMunj9HaRSrvWX6/ZRzFz1pVtpXCNlHSIlWMOwpVlaWKApPAzIab5KmY4bDPscPH+O9j99H6TkECZNihmCT40cPkKl5tMg4NHeA/ekSTCsQnrY6yzRJokiTxO883QiYUog0x6RDVG8RA0hTsvPJR7z427/Pr/3v/jainyCl9uUBVc10NuK7T3+Ht8pLrB3okaYZW9sTFhYXfH1jUeGo6PV79AeKyWSH2mgmM0tWCub6OZNpiSgyTmarXJ8NyaqSLO+RpCqAtP4+hUeePXbQKCYfEDj7+E+wZcWJv/ab5IM+vSzF1AVVZUnSlHcufsT7bDN3YIguDPtW50jnFePRlEGyQJJ7WVpcSzzAvSlIez66Z2rBZAwHl5c5euwoH579kHJWMJ4apFAsrvQoS0MxK8h7KWVhKIYDlIbhQsZcb54LZzaoa4f01PDIfs0g1VS1RWlBmifUtYAQPXOpRUpNmsUgBz5Qkm9z/KZFzp3bwSAwwmBKQ13U6FTRk7lPIi4qlMx8BYRzJEqxsLDArCyZjkocliS3aHyUN8m8OyulZW4hYzI1TLZrtFW+kN1VaJEghSTNJf1hwsb6DtkwxVmFo0ZnzldQOIG1mtlshta+E4wQFjGQ9AYphakwlUG4GqENAoVOBDrrkeQ1SlmSRDKdeeyuNwzslJWgv5BRVhOyxHHw6Aob61v0FmCwssDmaJtpZa6idT5DKd160yqrq8scK/tsbm6TZVDUBVtbExbnDYcPrPLJ+U/Yv7IfrbwJ6ag5cewwy/N9TD3l4GqKlQl1VTArBwzmcqQcoIVkYQDrG1PW9i0zP+x74E4Jzpz1imdxzrtymxsbLM7vcMN1GcL2mIwcad/Sy1LqUjHI+hw9fIJX33mJ/kAySHOWFjJKM+PaAwv0ekOKcsrcYJHVNYGVI4bDhOP7D3PxUsK5dUGiFzB2ilIFqRacOnSCDz4+xyBPWFte4+hyn53ZhKIaM7848GUcRUU/lxw5ssT2jsVQszMxLC+lSONYXJAc131AsTI8wsbWJir3tYEr88dwJmVhuozY9kmbUmh8VxhN1uv58ZA+GhMSEbw5nGjo9SHJkcbAZJ0X/8Vvs3zsAEfuuhmEoJxNEQKKuuK1ix+y2ZesrfU4fc1hpJZMqwolJZNiGy0TpKpIZMLcYB/nLp5ha1xRGsN0VnHi4AkuXtphv1pmeKmkN56Sppo0y3xgwVkQ2rd2UjLgU6EwGkiU5sNvPMXZp37KTX/3rzJ/7CC2rplOp2idU5YFZ+t1Phbnue7m/ew7lHN+dJ4k8ekjk6lkdWmV604ssjUqqYua/kDz8YVLGKGoqgrhEmalYz5VnDy+jEwvcvZSQb/OA3WNpapAqzkW5ntcurhOoubQiSLRjpMnDnNmFTa3RgjhN1DjDNZpptMCKR2DYUo5c2gtfJJnkuJEzeragMlkjKlKVvo5i4uSJOthxZjKpGyPxtSpJR1qlJRkPSgrQ+pSTlxzHe++/x6j6YTlYc71J49z7tIFPjr7CVIodiYTkkQwP99HSK8E+2lKlqa4SxVVUZGlAmcT+k5TVSW9PEUoy+LSHNN6xrA/x9LiMtNqjJUzdsZTZhNDqhOy0sMvde2jhgaDHlikVUiZeBka+6TnLFVonZImA/JUMdqckucePlw9OM/2aIdqpsgGmtJmHFxe4dCB/Vw4r3FCMBjkzM0klzZHf3Sl9Ll7TlGbAtQSgqNMJuewzlOWJtK7VccPpuxbOklV+j5wFzY+Zt/aPBJHlgxYnk+xGJJ0hapyyAScK1BKcvjgPLZOWV26lqqcUbkRRT1m/1IfqRzDfMDC/AFGO9tMpluoZJ59i8dwTrM5+phEJjinGU83OLAmWFm6HiEVc/0FinIbR4Uz4EJOlcVxcPUUmzufkGpLL98m2V+yf/8yuVhmOFhhMhsxLcYkSnFof4+VhSMkwo/8pNhhPL1Ing49XlUWCGfp9+aolzTr2x+yf2WZLHPkaZ9B2uP4gVspyinWFSwvLCKUTzbL1ArC9Nl60yFsRZ6o4Ib59wGUVugkDZiE9/994ahG5nO+oeNsRDW6yHs/fJqH/+afQWqJE4LxzhYXti5RDhJmc4IbrjvKwUNDlpZXmRUb4CqfqCnWMLUPLydJRj9f5dDaQWbFFtvjM2i5wPzgGorlmo3nP6E3seQ6Q/ZzdJp5P8R6Hm6pE1AKC8GN9+HgrTfe5ewPf8bJP/dr7LvxFBJHKn3KCAJmumQ0mJJoy4H5AyzNC45Wcz6apXooneIYY+yU6awmT9dQcsKJIwtsjwuMcVRVwbSuWB4usLw4I82GzC3U5NkQnOXShUts75QcPnCIwUBSXbNIpufIdMrW6BIHD89x+MAxtrYLkmTA1njE1miHze0JO6OKwSBhrpdibYIFJrOC4VzCXF+zuJyysVFhZhnHDh1mYUEhtGVpPqEoDZvbhiRJcE5R2zEyUcwmPi0mS7c4fDDFuh69tMewP2NlaZF9awIlhpy/eAGDJUkrsgyGvT69tA9oFuc0o1HK/GCFwXCRnekm7330Nv1Mk6aaui45ffIgc8M+OpFc2NygP8jpbcN4p2A46GFJmZUVdWExrgYsJ44dYWNj26dXOMt4PGPYy5gb5EynE1aWF8nSlI8+3iBLevSyhOWVnKo6wHha4KjQWnLy2GEWBgN2Dg95/+wHGLPDsSOHWd/o/9GVUr+XU1tJqueQDuZ6UBqDqWcM8gykZnn+IPPDw4zGOwCs7hvgmKBEgpID5vr7qOsxZVXSW1ygNhVVvYPWkjTZj7MaLXrk8/sZTT/EupTl4QJCpOTJIjpRLA1XPXOk2yZRKUql9PP9aJWQJQNmxT4SnWHqjF5vDmtBK0FVFaQ95S0Q54nsETDfG6KlQSnFpNhm0FvFGkGa9byCqadU1YiDq8fRsses3KY/XKE/y5mvQDk/qHphjbIcYUWFlJBn++jlizhn6PX6Pv9I9lieSxjPzqBUhlIZk+lFUjlgcqmHnY3Q1uJETVk7aiPo5YFuWPuoG0o1mJtMU0gHkA59omG5xfvf/zFZP+PIfTeBFEy2N/jgwodsJRUqyxEaFgfzZENJVY1YmFtAk1CbkspNMUaTpnMIFKmUSHLyrGYwOEgilqmnmvU3ztAb12QJJFmGHvQRToTCa8+jJITy/3aglKLf7zP68Ayv/aN/waH77uCm3/wTFMUEYQypsCS5pkgt9WrGwtxB1Nhi3DZzwz4Lw2sYzy5R1wVSpNROkqg5nEkQylJWjuHQ53gpMpIkZWc6Yi4fYp2mFvMcPlBRVlNSDfaaA8zKiiTxu32SZFRVhbEVq8U8vX5KlvThYIpE41zNaDrmzLmL6DQjTSX9VKN1n43tTTa3txn0Bsz1JUluKGbzpPIAWuRYsY1UNWp1QG1q0uQoWuQ+D0r54uNEDpjMthHCUZQWKQdIITHlFv1ByjWzZeaHBxjNttmZTBjPPiHPjE+2lXNAjj7RR4s+ZVEwK3dA9zm8psgSwdrSSbbGH7F/6XrKumJn9AnHZpYkzZgVFlMb+nlCbQuqumLQW2RjawtrHPsXD9Ef9Lm48Qm1NVR1SZ4q1lbWqKoEIS3GTjm4Ns90OmV5fpG54YD9S8e5uPkhtZ1SVgVZZlgaJpw+dgf7lvpsbH/E8nyfO6+/8Y+ulHr5MsY6Uj3PZHaeLJ9H1TXO5jhXo1UOTjArLgGGRA9J0wWKGWiVkOolJuWmr1x3l0CW5MkQZhV5uoxWOVnaZzK5RJrmzIlrmEy3yFPfGkmGxLEkyTCy8uwBGJyBuf4BrCvo9eZJkyWsK0gGOZPZNlql9PUQk6UokZLoPuPZRXI1ACuRoodlhHOSheG1OBRSWKwBjUMnc2TJAKU1ZTlDyQRTjkmEJctXSfQQY0uPH2Q9kH1SPWTYF1hTI5UPP2eJxNqKopqRZ4skekhVz5gfHqaYwPhiCbMKW/u0CfBNEGJpS6zcllIgdRISeTUuGfhcFFNjZjs8+09/mwf++q+jdEpZFRhnyPevkCzMM3EjhAZjCiQ+wREqbCB8F5Wilw8RQtPL5qjrCcqlCHrkvR5yPM9rz72FvDgmlRqtFWlvgNKpT4UwLadOqDBDKOHzVmYl7/3ud1g6cYx7/tZfZnFlkdksoSpmVLMJThnEkqbMJ6QyJcsyhKxwaMazj5HSkmUJRbnJwuAASgyobUFpNhmmaxTVNhKFEAqtNFk6T1mN0Ui0TMgTBaKPMWMStUCq5ijrEVonVNUEkeUIkVBVYx9sURnWeV4wwZDhYMDy/CJSZOgk8+6NndHLHMcOHEQKz9JgXcGkuEieLqDlPFXdw1EBgrqe0ssGfqzpUdkJWioqU9LrDanNDICl+RNMphMqk6B1gqkt1pbM65S1fUvMyh6CyrdLNzLkzml66TxlPcFYX3R8eG0F8EnH+/ddS6L7gMPuy5nOvDfgkyBrJBVaJcyKHdKkz7TYAQe9bD9p1uPA2jy1qSnrCaBIVI80yTBmgnV9luYnCOaYm1uhNhVL8z0Gw0NMZyNPGSMsSngldnD1AMsLA6RMULL+oyulRKVYM8G6GUmSYsyMJNEBkU9DwqOhtjtYp9GJRoiEleXT1GXB+vZHFPYcvXSZLE18pEIqEt2n31vyOYFCkOd9qmpMv7cGqNC3C4ydoJT2BbQUJLpPbWqybIhWKVUtvQuFZlpsYBmE1PYEhEUKRZYsIkVKoscIAXm2gEBS1WnI6hWU1TZa6pCmX2EpSJIeWg9RMicgxjh8rZdSmnI6RWtNInJ6/ZWGoqQodpBSUJYjZLAWrahwFBTVNqmeY25wmIvbW0y23sUaX1hZmRoV0iGk8IlvkT1AqhSRpgihQeWIfAgIqGe899TT6ERw+K4bcRgSnZDMzWHqEtVPUbOEyoyp65kvdVEDhFAopZCJxqjMJ03WFc4aalNgXYEzFaPtirPPfIQ+b+hlfVb27yfr9ZlMfbmINRVlNfNZwMBwOCTr9ZiVBdYYXv7H/5KNt97lC/+X/w3DfUskiSTLBkxGlh07Rc0rZvM1TmxTWU2/t49ZOUUrha0tAoMUKYuDQ+yMz5ClIGWGZIBAUtdjpBQkahD6BVpfqiTwXErEnKkeipxE9Xw5hvAUOUorcAlaDlBKo2Wfqi7Rifa0uK5GKYVWGY6ayKuVZz2ybI5Mz1ObgrKqSdXAJ83aEUmiUeyjNiNKu0FZSpJkiGGbyXTEIF8i1fNU9cjjWmqIqQV5NsDOZiQqQfp8c2ozwlIz7K+F9IcZRbFDrhepzYx+r4euHHUtqO0UISxVVZPoHv38EHU9xtQFWkvyhX1Ya+jnGTqZZ3t0hiQZoPUAKUCrjLKeoHQBGLI0JbU9ct1DSo2QPvJblVAbSzKY9+VbboZzhtH0HFCSpUMStYyhoK4mgGBx7gCTSUYvX/HGzB9VKZmqJNGaXjYPYpHJ9BK4GQ6LVrlvy4UlS1Yp7Axr/e4wGm+htCBJc5yZR+shWZL5qnln0KJHVc6wtkb+/0j702Br0/2sD/vd4zOtaQ/v0N2nz6BzNHA0IIHF4OAEY0BYYCwIKTuYVBISV2LhcoJNDPmUEJIKVLkIKcoxg5EIRiaQFJFtQAyJEQZkIQkJEGg4OlOfnt5p77XX8Az3nA/36j6CEFw5Z3/oeru73vfda+313Pd/uK7fJTu0GBCyMM/PKTmSkaRcV6/OOzbDa0xLRClN2zYEn6EYpBgwRkPRKGmRUrGkI5kFJTUpVg9TYztS2QC5/p0orL4iZ8d5uaNteqzqyamgGsXoj5QSCdHR2hUUxRJHXDjSiR2FhlQCqgw1DDJljNakBM7foVXV5+Qk6dqW2dXXKkQdRD4c3uf+ZSAvApEv4QQ5I4X88FCKIRFjrCAyWbUuRStoO4ptoETSec+Pfe+f4Zf/m//dulYuhWwNx/GIlwHcS3KeEaKhaXqW5YwQir7dsvgTRhe0koQULll6M0pJoMEvihc/8nnsHj7ykSd87JMf5/bNT4BtcLPj4f6BZ1/6EuVciMnRdT1X1zdordHzzOf+yt/g4TNf4Bf92/8jmqs1wY1ooWg7g5QJPRj8ur6mRj3CmAFr1uS8J8QFJW1tE9JMTA8M3XWNDheSEgKQGJrHCKHR2uL8GSFAqYYQz5dLdUMqM0a1NGYFJWFNg1Its6sccKkESlqG/hHzcqAIV0W4ObHqnzK7Iyl7Qhxp7Roteob26iIk9aTsUNKg1aZ+b6JgdE/bbDieRlq7QWBYD0/xYUTJFikMjb2pAkc+oFx6UvKsuhtCXCiMSJmQpUFLSwqeVAJdu0GbNUJnYkrM/r6OMeyO7AohjgihsfoK7xZiWhDioudKCilbiki1mrZX5Ax9e0NKnr69ZZoPzP4FRncUUVC2oRRV9VjJoy76OKnL5aAuGDWAWFj8S4xuEEXSmCqvyWVBqRWd3RLDwry8h9FfxaFk7ZqUFpSyeDdiVUMRhlwSTbcjBk/KS53/tLUSkqKhaTqm+b5+MOQWiSaljJItWmmKLAhZh5MxBIRuyNGDqMrUEBwUwap/wnl6QOQEEXJ2hKTqgFYVYpwAc+F8O8jQdg0uVvd7Z3f4cCanmZQWQKFkW0t802BUj18C29UbpORBBLLQxJhx4UDX3jBOd2yGq9qSZElIM9N8R06BpAIhavpOsN+PSOWZ3EuaZsDqa3IRLH7BhxPWtJANkEkBpv0C8XJIilTbnYsDO+VMiakqeMXFYyQNQjXQrCgSRAi89Tf+FtoqPvKLP11tBtqSVGLG4/KIUQUpNW2zomRJsYpx2jOWB6zpgKpvEQK0kYgScGHG7wvPfvIl67DjG77xdTZXPZubW2xjKCVjNgOr7YpVb3n/rXdY5jPaWqzVgOThJ3+Wz3zf9/NN/8Zv4skv+ka8Gzkdz2i5YZkPCCHorgbOdq4I3BzqIewfSCli9apWNdKzzCOt7XB+BNZIoaqAULX09hGQ6gMXC1rLWiHLwqp7g3mZoKzRur2ICQMhLbg4XdA0kpxhWt6vt/3l0lRioBCZpjtKSRjTUkpXLRnZoTFYO5DRuPEVWjZA1fq0Zk3JhZQCSkmU2ZKzJMa67Mh5ooiGxrTktGF2Z4qacP6MNh0+Hig5YrQhl4IU8wV7PBDzmZg91mwJIaJVQKlatSQc1m4vAuCACyeUsChlEFJfNpACRKnPtGwRZGIKlBzIMZKkqc+vviZlX3/vBw7gDEb1aGXwKSKlIaRCiBPGtJAzjVljlK0K9BQoJVJIhHjmOL0kpNOH3siv+FDS2pBKYPY1J8zaNW2z5XTek4tC6g6ixNiuUufSRIhnSonV0FcUUlmUqjoKaywUyxJHtBB0zRWxSkFRsqEgiPlMazeE6Mi5tpAujAiVKMiLMnrgPN0hlam2DyGrsFBXmb2SkpQgFEfbbEhpJqRDvaWKxtqOlBfO85HN+gotW46n5xRxRpsVfbsmRUffbMjZ4cIBKTooBh8mtNJY3dZWUWSmZU8uAb94bnafAJpqXxCSth3wcSSTsaaBrDjtR4pLwOV9In3ZAX6h+QEfAtoRAiEtxQygO0SRpPMDP/Y9f5pf9tt/Y13LG4OwDW56ICqBzIqcU90+ZU1KHqMbtLaUXFCyr7eaiEzLHU3TU5DM58jzf/gO137Fpz71Gt1gUaZFNx2oGn4ppIIQ0CXRGEFJDU3fo7Xm+O5zfvJP/3k+9S//Sr7lX/v1hByxKuDOE34ZsY3l+vFTjiaitcSnWvVkCka1l7a7IGQgxAWt+0qSoLbqShXIlfEV0hGKJKVwmSt1xFxJorPbU7Iml0hygQIY3VKpXImYPUpa2maLUZbFP9QUDtkgZKHTW0qJ+DAjhcFqRWL80OKR8lKtTsJSikZJjY8nvJgQWaCVRcsOZCKLgpKWQqZrbhHCMC13eH+ksVdobfCc0dJenqMz2e1pmzVK7VBCI7VEpnX9eJDJxZFSoLHXWNPhwxkorPtHH+JlcqlJyVr21d8mC1IKlFBYvaaoyOwecOFItTBIYvIYvSamMyktdVMuL4dwzuS8kIpHCUnXbNCqRYoWLWtFqEQhi1itXspiSotUBa0tWj8ipDOt2Xzlh1JKAq1WIDKzuwNq0mxrdyz+iFRQiKTkL3/ppj60WqNkIUVTh9QpoqgfiJDOWK0xuiXERIgzpQT6dkXJFRkSQqCxq7qh06/RtA2H0zNSiWgliWlBK4s1a6SC03mPlE11RYuAEC23Vx/jdLqrJ75sWfdvUPIHlhSBVpvLTMlzHL/E1fY15uVALB5Bom1s1aIIMGpHKhJrEpYeaxokkPICSLRakbuq+E4pkEt9PygW7z3WrHk4vcd6MBgGpodEch6JR6jq5ZOiOsBTTsScEEqirUEaA1qTtUI0LUiNiIEv/OBfRxB54xd/M0Vp0C1ZGFIEoRuaPKBtTykQwhlxOaiN7tGqRyuLDwdycrVqygqC4uU/2nMjdnzszRuGVYvSlm491GF2ykhVDa8xBE4PR4ILH6rP/TTzt37//wVtDd/+b/5Wmr5H+hnnoW0bNo8ec/34KVkkZveMYkCV+n0pOgQ9jaFuBaMjp4I1HTlLGrsl50BKAa2b+l6HhaF7TNbg44RzI1IllBxIMWBMixEtMdYHuBTo+yum6Uhhru2+u0cKhTWrevD8vCQdQYtWH3C6MiLVmUpKjkJByY5GX9E0G3IWKD2gpUYWT8q+kixkS44eKRtI+bLYucfHhbbpKwEgG7TskaKlaRpKpG5XpaLRK6Rsa5UhLSk5jJFIu6LQ1+qtOIy2iMvjnHMkl0hBgYw4f19bw/5xHQmITAoRrXu6RuGDQ8uGVnVM5YAUmdZcMS0vsKqtn8uwkEq8bFYtVg+ESyJOKQolJTkJjGmZwz2ZEaNuUeKaXAIpORARhGd2L77yQ8nHGWt6rBnwyxGjLRRDiGO9RVyspEgrcH6ktT1Wm8prSQqlJAJTNxpGXfgz1cOlTcPiD0hZLQYujAzdlnGWbDc3VdsTZoRIhFnSNgPzcrpkmlcWdUgzIkr6bg1FXRzIkZJgPD9gtaHIRAiOod0SgkNrqqnUNqTsQEDfXnM8P8OYhpIiUrco2dSBsKj4B6ssii1CGabpJW3TYPWG2Tt8GOnbrs6EZEvO9fcobfDRsbhT3ebJhmma8UtEpIiStSwuQiAuMLgPoqqU1khTTa5cVNzFdLXkPt/xI//R9/K1/9I/V13upqHoHrJjSSORmZgcMmvO8z1DOxBDQitVfYm6ute1ahDK1gtiSbzzU++yXlpe2/b0g63uf2XqsP/iBi+5zhLG44HzscpApK4btX/wn/x5Skr8uv/j/5r1zRVSKlqj6bSiGxq63ZasFOP0inNZgPqzL1nU1k/UyyrGO0KY669Ddch/OdFDIIUml4RUmpAWpGhRSjPNgV5v6pJBVl9mxqNUg9EDMSZSTLRmVVuLfAHgq4xWDS5MKFE3W1obKBKwxDzRNht8MGQcJUe65oaUy8VnFuqvL59lpK0aK6kRWCSJkipFIMSZrrumzZWHFNKIwCClwS0n7DBwtfkEp+k5UoYayd6s4aIjMqalkLBmhQtHUloQMiCos18pLNNSt+HLXC+Mzeo1UhJMyx5rJbHMiGIQWdXnV7RY3VJcZGW3nJYHkpqRQqKUxLuZIhxNe0spBecnrIZGr3AeiogfEgBmXy+NVCLkiFF99TXKQszUylKEr/xQWq8eMc1HYoz03Q2pnIjR0Xc3WNXWBVBaGNprpnwgpbEO/UQLqHpiI3FhIoRCa+vpKhWEOOPDmWFYk5IhZ00umqurj7FdPWV/eBeBw0dXT3LVIKB+mIREyVUta4Ug5YqdUFoSU93wUSq2JERJzJ7j9AqrWqztaYy56Fd2CJnJOdF1K4xao+SEtU0d3lE/Y0JGnFtAZvr2mmg9UmSkNPWQy4mQYv3wlYSShhgDPi7ElMi5et8EGlECyYcKEUBQRPwQn4IQKGVomw5jG5QyVcGtDELZamyMC1/46/9vxhfP+Mbf8C9SVIOwA0JYchgZ/QOzOJNKJMTaenhf1eJSGlq7xeorCpEQJnJ2LC7yzt97H7PPrG2h7y6m2gtXqogvJ1UgoYTIMs4XQ2pV8v/sf/7/4ud+4K/za37v/4rHX/cpGtPU39frKmmINZI7uwOTjCjdglAIJUnRE5OjaYZLdWyJEaxuoNSWM+YZKUrdbClDbXara73gK5li2FJyrm2PNKTiK9bkQ0BaqsPpFBFCkFKma68+VHxrtb5svT6wYUSs7ZBJ1haygBRdrbTlFZSFmM51E6WbWp0Uj9IN1gyQC0o1F9lCopR4ofAmBIFMQSuLuFhDiglIqkFZMKFENfg+HN4DIkJZ2naFEOpizq5yiBCmWvnGE0o2dU6pW7ZXK2IaL/OhlqHbEvOEkRtScpzmI12zqsbs6JAxYUVLYywhJbr+hlJqQlG6wBbrZSBx/oxREa00GUXMEa0VOVUGFLm+fy7ukaoQo6kDelFQ8quYKS3+ASmrBiRFT2u3uLKQkqt6D9WhZUcICymfKcURYkSQsaanbbYXXOZSmTGmp2u3LO6BlBeadqititC1bC2Fab4nhBNatyRfzX5a2xrXUgIpBITSrIdrlikyugNFTCjRIkV3wUlIhNJkkWoZrWQlG6qOUgw+eVKODP2uto8EShH4cKqD5qgoRTF0N/gYSeWIMqIO/GOdJbR2gxTQtQ1GW0L0lMuGTZtVbSXxnKcjXdtUJz+Z4BN+urCo+QATLZBSUagHh1IGfRFMCq1AWYpsIEXi8RU/+kf/JN/2r/8G+s0Gmo5iVnBJKjlO97Dp6fU13p9Zd1f178gXIJqoIT7zcqSQSUHx/DMvye+PpGWmXK8ISUAEKypkNMRYmUoXzEt0DmMtzTAQY+T9H/+H/Oz3/1V+yf/8t/GRX/KtNYG3ldiu+zLTKAWKHzmkiXMHIRaslrVSFolCNe0el/cu4LZKkhRFVH9YckhhiHmBy3/POVaYGrJC9ARkGS4olIUQ60PTNg3eJ4TSkOtlqXRPazWlBFx4wOpdlTlEh9YWJS2RSEi1lQuXZYkQmhgiSlXtUWNWSOr7o6itUMoRkKQUabRGmRbvxoorEdWW490BaRu0bojxDEKgrSWJMz4GkB3KDORYahJNRVriw0zX7pjm+mxuhteZlwdSmWsRkGOlkMqqxZLCXAbPVY6SMhizJoqGlI5I3aOkJmZHUYUkE0VYtDV1bhc8xnSQukvIhcDoFZJMDA6lQKse21icP5HLjEJj9IZV+5hx3ldTedZAxoXTP85K///3UCqlYHVLygkhDUo2IFwtQZsdKQli9qT5SIgViRDjgpIwdDdM04SQ/qLurlaJmCaU1CxuorFbFjdjrSAXDx/YLFJCq4wLU21lpCREh2mqj6ltesb5rt6kPhDjhc2UR0CR0okUuWiKWpSslhBr6nwsuJG+vyL6iJIN8+IwVpMBa9bVD6Yt52VfSZqyzrFcGOm7G0quW6txOZNTpLXXtHpg8idyCSz+fLnJC+vhET6eETKgpEEJhciCykeshxHUraWUGq00Wmts22CsAW0QulpNSnJ88W/8Tc7PX/KNv/FXI5oG7JYiLaSJJS2otiHmmtmHMIQUK3s5hgsULXyo98oZXn72wPRzd8jlhJaSVASLK6SLezymhEoXLrf3jIcjIVS4nzWG87OX/PAf+hM8/vTX8bW/9lcyHieM7pFqQhWHoG4Rs5845zMP2pN1U9XgyeP9TGsfXfxzAakMjW4JhIveJuPTvh7q0lDihHMHINI117XNloaU6ywSBCFOKKGQFHIMRFWTcpWi6m1U5ZTkXOcvSlUKqBQXt76oa3AlFIWFkBKNGlii4HR+gVaaeT6wWt1QRCbmBTceK72BTInugoS5RBFZRRGSptnW1x0j2SQQCS1bumHFeXxFSoElTkjR0TY3hDhBKVV9HjM5VyGtcxNKW2IILO4MF7RzSiMIWeU6uZDygjbbOrcSmpg8KQtkDrViUbrq0kjkFBAikcpCa6qeCwFIWT9DOWFkQz/csiwjQgSU0ihlAUXJ5TIa0IBCUI3MBcnipg/JsNa0NHb1lR9KOWSKSEip8XGi5PnDF7M4j202kMAaS98ZxuWMVNVTNbuJrt2xOGiaa4xuUUpVal5wGK0vb37VlWhduTtCaIxZEXPEND0xxFoeW0UIMzF4pCyUIvHFgDRoqxBS492Jtt0g6FAy1gc+67ppKPW2yLFyub07EHzA2p6UA4oGqRq0XSGDJxd/idipNEolWooU3B/exZqB4xjZbW4YT6/wfk9KHRViUTeJAkEqnpSrZQVZGNoNOU/klCpOVCiUakCAlvZCQlTIi85JKA2mrYSsNJHGPX/nj/0pvvVf+07aqw1luAa7qhVamut8xaxplMWHhLYDWtfyXqjmEsGeMbpH6YYXX3zB6Qt71HxES1ErG6VJBXRlkKCNpe06mr4lxsh8d1+hcI3AHc788B/+Xm4++XF++b/9P8bPBSkUUgRIGT8F5CW7PYSJs3KMMiCigJJJqZCyQ9oVSnY8nN6lsasqGJUCURQpe4zpCX4iZUfMM1atL+ZkiHlC5BahLE3TEvyFX64Hgg8oq5FiwHaG2b+qm6scyaTLPFNgVK2wY3S18sqhVutSX5ahnpAdyrT0w5a+3YGo1UXKHh8cQlTGdwz1YjZaMzQ9SgmCPwGVBiBKTTG2zYoQJqb5RE+DlJWHbdQaKRXeH/B+Zru6wZieUiTSWEJYkErTmIEpneohSKCxHTnbOtnJuW7IlMGaHbnEag/LVQStZUuIrjKwpLrA6CxSGMb5FXM+YVQdwivZEsKRVBZIiTh5cla1xYuegkFrSYgTWkuMWhHjhQSaExRTOWm5Bm0gDD76r/xQMnpbhWzqAokSddMUUyKLSKFiNlfDbWUyZ0/TbC+xSgLnEuN4pu0M83KoswUxVPuKl0zTESkNfb9jWh6QUhPCwrxUeqW1HY1dVXxoKkjRIkThPD1c1tprlKprd4Gib1bEEDBmQIiFxZ0RIlSVdl6qeExotGmZlxNCCGZ3xpotOX6Q0lEVqCV1GGNZ/F2dI8UaYnC7/QTn6QGlYi3jjUWS64FbxIeeMq0bVG4r0kJbFjeTda5wOfRFaAdZyLqKFqIqklVNhzHG1pZJqopUzZ63fvBvcXr+im/8ru9AmoHcPUJIg4gzMYzMKVS7SnIkMipLUix4v9AYgxSqQuxUw3jUvPqpl6jxTKMKtunQXQuXlrHC9BNt22C7FmE0cZ6JIaCUwjvHj33P/437z77Fr/69/y5St5wPI7evXSNUqodOdkAhZsexTJwGi+l2VbcmAkVEYhxZ5j0gGc975EoSfN0wGdMyuyNCSIxuiDFh9LZu3rInp+q9U7LewN77y2eo4ENlPeVUMFahZUNQDUJosq5D5hoimkipYG1TgYWXGLC2HS7VXEDLhsmNWKPRckCIOrcBiRId1ih8KJSsEaLOHZWsSxLn9xTih+ZjqwecXy5ug2tWrWWc7zGmRYhquwrR48VEY3ukbHDOIZXG6AbvJyiVd26sZHEnpKxapVIESlbfZPSOVDzwHCn62umIDoHEhwlrO3S2tQvxgRBHNuvXIN/g4lw/nwUau8E5h1YSLSGEQGtuuFq9yavD5xAqVAGpMqQk8MEz9Fucc4BAybZeLFYS81xlD19NmomSA8Pw6MLdrirpkjTb4Yrj9B5KGHSrKoJCWob2GqUGGiUpZGIM7LYfqR/OMqOk4Xr3JrkYJHWA2ZiBnGFoLC7M2G5H1+5IMddtmVBIpWiaDedpjzITWS+M0wEhSl2Bl7YKKEtEoClZ4XzlCHXdUF3wimoKtj2Cpm42pEGrlkKk1T3eZ1Ks2V9CSIyxWL1ByQ5UrLoZMbBqLBlPJjDNJzarp4QYUDoRQ6h+Ib9gzUAqtaUwxgARKdqaUSY+YA5VaZIUYJWkbdq62bMGqVRNB/GecLrnh//Y9/GLfuu/QrddU7ptFVNGT4kTwZ0JChrTEOIMPpCKRMsVjekxptIIh/Ypp8PEF3/8s6jziFZVP1VTVQzkQte21eOmNDUwK5OdZzqeqgWkFH7qP/9rvPVf/11+5e/5bh593dfgFrh6vKVfm/rQxOrpc8UxRUe63kCjUUIRnaLrN8zzAZLBpwmpLNvdE8DQtWum+SWNNGyG12uFHCOtHVCiJaYZ72f69rqadVO8HPR1Btk3jxBCEoJDiEjKY93USlFbaJkvw19FzqKavDFIVWmk8iIVU0oikkPKFSvZg7AIW4gxomWHkRZrO87TgXa1puSED9XLprSlxEjf3qJkh091FpkLGNOi6LDNltPpBY3VGLUlpYR3DmObi/rfES8BrAhFTgF94XyXEjme7rC2I0eY3RGlBMb0qGIAXe1KorZY1vaM4z1du2JxD+RUH/36/WYau8L7iZzDRVhb/YvOnem6FTkHRC5oG4lhZnIHhKxVF1BbOikv1Z+8+Ahr1VolGTUPzmqF8/NXfig9uf00KUWOp5d12CVhcgfKMnK9+yQIg1aSaTyz6m8ufN4K7C9ZXqiJiRACQ7fB+Ylh2HE+H1ndXNcBeYq0TYfV9sKtqT80Hz3WWuZxpO96zvORoW0xujKG1G3trY3psaanlPpDyyVh9cDxfMduPRLTWN3rAEaxGR6hlODl/Xtstlu8X0g50JgNV+stx/Ge642hUGHsUkoWN9Lahv7q6mJCrrfe4fiK7voJQ3/FeXyFj2c2m1tSSpUs0Pf4MF/sN5JWbYh9oMiXSBnrrA5QogYLKClorKG1DUJpijbViBsDX/qhH+P84hXf9F2/FmEasD0UKNmRl5FxcSTTIYtk1d2Sm4DzC20z4HIBEjF6yIbnX3yGv3uByR5jZDWbykqq1EZjG4s1BtvYumk5j8RYf45FCu4/9yV+8s/9F3ztr/3v8ORbP41UDautIRdHiAuUSC4O8sKcMnJ3g7l+k5ILi79DKUNjrlFyw3bzJi/vP4dQicZuSamu141eI8pASnUwPTRrNquPQGnx4YQUPVr2DN018zxTZCaKuzpszZJVf8Mw7HAXqwXlwsEO+UJ27Ojba6b5gJEt69UVh+MzMuGyRfsg9SZh1AothxopJkFJzXp4SoqBrlkTvCKLmdHd03Udbp7JIZGj4HrzcWIshPicxqyIMdHYhkbtaJodzgfWqzXLUvn2UhpW6y0heKQSODfWy9kIluVICAGZI1Jqhv4RkioRqJWKp7HtZX5m65+XDUo3SFqs3kEpSLFGSVGJnllTcFW4W6rjoDNbcoYQR4zqQUrmeE9jGmJQZHnCpZfYpiWGjDUrNpueedmDaBm6W3LS+HAiEyCLD7etPgik/CpwuM9e/hzWtKTimKYDBYORBh8OjJPAh4CU9SR0/lCNqt6RykKMyyVoUjD0W2IaUVJzOkVe3n2Rvl/Rtj3zPDNOAaMNztX47Oq/qgPfadyzDhvO84gQAu8X+qHqZmL0KNlhTFfXj36mlMx2fc2Luy9wff16HcanA123RgjF8XyP1oK2bZimiUIkxhlE4HB+xnb7mPG0BxGIMbHbPqVt1pQs8D6wlAWKxBiDthCjutzi1+y2r0M0ZKrSdnFHrBqwXR1iG2mZz68uhsSRD/LYu65BC+gaSzd0tG2Lbtu6WVOKNJ35ke/9M3zbv/GbaK+voN2B6iEFRKjD0NRs2Q03SN3U7U5Y2AyXFBBG+nZNLpH9q4nDl17RxlAjoLSqcgNV28j1qrbA6/WKbuiRShGCJzgHpfDw9nv89f/dH+Lj/+1fyi/8H/wmkBUMFvyMVKkaaUWudAR3Ivav8+TNb4Nhi1EdIc7My8MlHFKSiudq91HO0wsau0OLDSl7tOzYrmp7GpOjMZVIoWR9fdvVm/U91YbWnPGpCilL+SDbrV5EjY511hTixcoD4/SAbDQIxWuP3oAimN2J7eZT+DCSsqNr1jh3xnYdu82b5BQZ3eny+bRY3VNKQQlFd3vDuExs+o9XWcdGEEOqMLSmx4epjixKwegWKaqqGiW5lZ9CSsnQ1gzoD2KibFtN0s1QjbelRKy8pm9fI4tAY3tOxxPG1B1uvqShaKvIKdM1A9N8pJTE0L9GzAutiZSs2A0N83LCh4nHN4/wziNNheXJCgqn764I0dOYjskfSEmjhaXt+4vfT+LCmZxPKGWQwmKVoG8fM3SPSTEDviacDJW9H7KnbVaM0/ErP5T2p8/Q2BXLcgAZaNs1+/NEZ3tO53cJaeFm90mm+ch9eEnXboihpoF4Xz0xUnQ4J/Fh5PjwAtvY+usx1gGv6RjnO0ouDP0jUkp0XYt3nnk50ljN2ekL+KyWlBHLw3HPOD+w7t6gJEXbNsQU0KrhOL7D4l6SH+7JCYrwuDgwzyNDf81yGEEkZjciiLW6SxWbGsvHcG6qUobk2Z8+w277mGXxFVpvW+bpfMGDGlKMGGsupsvbGoGdHKVkzvOevh/IqULPyJK7954jSlUTZwSqgBYaqyV929G1HdZahDYXfZLirf/6Rzm9fMU3fdd31MQMu6IICfFMWU6M/sSYHOk44V0A7S6q7Q4pW6Qol0VF5sWXPo+YRhSVYqguw1xrFev1mmHo0dbWw+oSlhiCJ8WIH2f+/n/6/Shj+Kbf8usRWlNy1d8IGckXqUXKtXWbc2DzeMOL8R20v8eFCWsMIThCWlCycDq/opB4uX+P1aqnMVu2q6dYs+PuUD1hUkJBoqVE61qphjBjdUffbUmJaibWGqk0MRZcOLC4M9N8R2N7NsMt81y9Yw/HZ5ff52jbDm0sq+YJOQeaZiCGlq69wpodAON8xmpD16zwwRGzZ394j77bXggFjnmplTHAtMy1BRKF83yk5ETTtEzTA6fxJVLAqr+5IHMU43xCSUnMtZp1fqRrDOfzCSETq6Eqsat1o2G9fkSMkVVvLvSOSCmRGBKyKETJtOYaLW9Y3ERrN/jQ1ESWC3jverdlcSPTsmfod3gX8P7A0F9ThCAkRyqRcXEY0/L4+lOIoliWiW64BVGXWX07k5Og61aI7DG6cq+MqsnN6pLKK4Qku4o+bpr1V34oSSkI4YzRlpgFyzKCCDRNdRX7OHM8v3VRbLdM40TMC123IxdPjHVzMU4vaGytlrI70tiBgmCazhQCRlmSXJiXVyAs8TQxLwe6ZkvbXjPPD7hwIqWAxNClDYs7onXVqpQCIXqcP2CbFpklRUTu92+z3e7wofbKs3sgxImYRnyYaNvrunUJS9XKCMPp9LwaGEtEq4b94R3G6Z7N5oaSDG3X0raW+8OXKDOsh5t6iBE4nr5AKTO5SCgtNzdPmJdqQNXFskwTKUqE2qK3K2zTsh56uqahsYbeGpQR5AaE6UA3BOf44T/2p/hFv/U30V+tKNpSlIGSIM64ec/b919klHPdzOi6vVT6wLLUbUvbrjlNQBC8euenUWWhprHWaOW2tWw2PavNBmPtJccsM55PgCCFRFwcP/LHvo+XP/Vz/Orf97tornbknCpe5CJATTkSUtWxJSJp0/FifpfiE9auCMnhvau2hVQph33/mNVww2r1lIfje5SSGKc9Tk9oI+rPLCSm+cCj69dwvm53lQQtDPdHi9K2eg99QukK+T9N97UlLTOzMzwcP8uyHClCMXTXpHLktDzj7lQJi40Y6LotUlkau2J/bi5Ka4n3J3J2FTinbX1sRMSMLVr1hDgS4kS6X/BhRmDR2mB1T2PX+OAqWqfU/59StR41TaUJTNNUt3fGMk172sayPxem+aFWJfct3ke6blMvklcKKcvFoiW52r3GssSL4r4CxtW+HgZGt9wdBf4ir0HU4bhWCq1aZr9HKRjnO9qmo112zJNDyf4iT2lIOdI2A11zXREl3pGiI6Zqks+5sC23PBxfYc0KNULIIyUrrGnq2IBC217Vn5ObeOP601/ZoTS7lwztNctyjzCCEGpMTUyPSLH2/YufqvPXSXLx2KZlcQ91W5I8PowY3dA2HfO0JxdH26w5nfesVmucn5BKocUK52sffTruq0Zq3WF0T25yLZtbe1FLJ6zagPT1Q64iblpY3ANrcU2Nso6M8wGhClJ55uVc1ahSIEXLbnNTMQ45EmSLMQ3T9O5F+LXj7uELCDmyGV6v/CXvkDLw/MXLWj3EBYFidkes6mntijmNlKJYt9c4HzmdX11WvwnvNEY95fWPvc76a6/ZbneVcX2JtRYCRK6kAJEjInsg8fYP/xDnZy/49Hd9ZzXm6noDl7CQ3ZG76RUPYY9sLbYZ6LsnPJzeR0ZNSoHzeOBqazGqZf/snjKGSrosNf7GWo1Whr5fY22LsRp7qZS89wSfSSHzpR/+Cd76Wz/Ct/9P//usXnt8qXgiqbga7SOrQz+XQCTiWoO9uabgiSFSwj05C9pmy3ncf2gDkVJwOt8T80RM5zrfUnWzO44ntG3oux1KSc7jPT46hv6KkAK+OJRsOB1fgICuveJ0d0ffbslFkmNFsYQSGLoVSreM00Iukdk/4INjcQ4hNMOmRSrJeX7B7O7RuiX4QNP05FLtGhFPXGI1htuGlGakOBOTZ5zv8P5E2/bkJAhJEmIHItcBchkJ2RFKwFpDSGdkTORSzcgpLoRU02WdjygNhYWh2xHSgqa+t8tyQJRA2xp8GtF64O4w451ntbrC+7o5HJcRKRrGubDZbBj9K+TFn+bCHqUzgh7vPYgJYzQhe0rwCNUTwozWK5w/gvSM84nT9DaFxDgeqrRAdRQWZvfA/dkSQ6KxLUJdSASqw/uxmsBLQh7th6bwr7hSMqLHuYm+3+H8jBaWvt8yLQcEAq06fHC0SrHMC1074N0BY27q7REODP0VWg0syx1t11BKtadkIsfzgbarFhOfFrRuoGiudk8JfmJyr6o25ZJ3ppXB+2pJMMbQNY+wu57jeU82imGwFyf5RZ+RM6v2qt4MViDoscaiTTVgOu9Z/ANtMxCjZ736CDFEcgpshicUkTmdH9DK0jSGECOr/rZ62bpVTaTIBV9mun4gTYqYPDk/1KrOtqRRsbJv8rGPfivb9VVlWYsPiAD1H1VmKS6J5AIwle7pFz7/X/4Q3/rb/ye0b3ySEg4IqcjRQVgYz694Mb8iyVg9Yt2K++MLjOovUDfDeriuKAufON/dw+IhSQQF06q6ZWs7lOlQ+su5fR/EIoHk2U/+DH/7D/0Jvu1/+Fv4xL/4z6N1pQlqK8g+V/NsKOQSccHjNIjdDtXvKOcH1pvHHI/vVgnGcmLoN7T2msPpXabprsLFwplcPN4FtBSYpkUKxTSf2ay2iCJpm+4ynxRo25HSfNlclkpukJa+XRNjQchEYkbLLUpkGrNi8ZK20XXJUDJd1xFzpS1+0BZu+tfQWjEt1XCudYP3mRhzrQwKxDSitbhEwAdinujaDUpqQjoiZAJ6Sq74ksZuGfQNd8e3iP6EKBkfRtqmEj8FkRACXdvTaMVhfJfiF3KG1t7WvDpAqgQx07U7jJaX5Y6BYrBWsMzVR+f8AzFNaDUwueccn3m2m0dEb6sZN12IG8ailSATaJstizuT84JINQ04lZEiMs4fL2ifhBSapm0vAZSBebknpAkjW9r2ilRGckyV7loiUiW01nhftUs+zjj/VZAnlWpobA8IWtOyurrlNB4IcU/Kmqvd6yAEzt3TtVusGRhMC8Jwnjzr1WNKkWhtiEWy+BGlDcfxDqkVQ/eIaZrqzV9g9q+wqseoG9bDY17uv4QUjnE6s1rt8HGi71oEHW4JaL1hnF+iVGJxdW28XV1XyJecaAzkNFOKJ6e+/j1C4LzH+wMgETSUbFl1jxinV/Wmmu+4vfoEIQXs9YoY6i2l9VwpkELh3cJq/Qh/4T57n2jaLb3YonUHsiOHDY+vvp5HN7WyqKZWiLlmd32QTf/BUVSTxT6IDy08fOZzvPtjf5ff8rt/N2q4hrglR0dJI8UfeX58RtAtDQahNKfziZwi20e33N2fsdJyGo80bcO6uyUvpSbpAlJUZ79uLd1qVSPHU9XsKF0H8DkLxpf3/Pj/9f/O02/5BXztr/kVSCOQunJ4cnYXBlSqt3iYOcQFfXtDEo5wukeJGqBIsTy+/lpe3H2WeZlQsqv0SyXrcFhXJbdzCyllDqcjkAkpch5f0jXVVKvVwMv9P6JrVyg5oLWgMddAqBBCBH23q+JbaXD+XOeVXQARaZoOIQyzO+L8Qt9tKRmcP9PaNclHpmW8KJALUmaEiHV+ONcwxaa9YXJHSjmzHp4S55GUPG3bkaa6GWzMmuA99w9vYe0a5Te1yhEBIQxde0VrrzieD6R8RIkeLS0hzqz6W3xwSNEyTifatsP5c21ZddUAUhqUMBitmeYjWlS/Z0gjJQjadss4vcCYhsbsoNi6WIg1xNLHU818yJGh3zJOxw/x1lJBY3qO53dobJXPWNPTNGvmeQQKLk5EZppmy6AfYXTHOL9AZIuWmr4bmJczPmZKHonF0dinOH/kvyH27cMn4J/65dwRqWrv2vUt8zyz6m9IsRIA9odnHI7PcWGibS+aHGl4OL1PSEeUVihlWfzM5PfV3aw7unZFioHF3VMYoQSGvsMoRdMUcpmQuqBNzZrqu5a2kWjjKMWT8oSPJ47n98hlYl7q7VRX2A3Oj7Vn1opCoGu3CKHx4YDz46UFzHgXMbqiVF041Qej2eGCY/Ejy+LRqsXaAe8vnJlQeO3223hy801Vr2Jqbx7igvMTLgikuCGnpwyPfgmxfUoSllQgkMhEJB5wlHShdX6IyvjyVymFH/+Tf5JP/svfhb2+pUhBtj2iWSPlwGlMPISCNgYf6yB1NawwVrI/vM3i9wgpWa12Vd08ReJckAWUKLSdRTctpuuRprruc67qdUqF/0fn+cHf/x8ihOCf/1/+dmRb8cfV37WQsydnXwe97sTL8Y68tqihQ4hCzgFtetzsUDozh3uGYctquMGFqVaVRSCkZJrP+OCZZk+IFQXb2CtyrJHex/MJRMP+9IzGrmjsdcXC6A1X669ns/4oja1r9roeT6QQyGlBCslp3NdACb0i54aSq7Ay+MJ6eMp6eHpxEgScd3TtFhBM86FqgVIkxomcZ0KYCD5A0ZR8UTGniZgWGnuFlC1D95Suu0GIjhgdo3v3Yu2RFwlL5MX9zzHOz6pWD8/kHvBx4Xge0abDmA1CNEzLzBLmmi2YOwoS5yIxOgSKzt7Q2RtAkBE07TXTPNeZAJXa4X0keVl1RUlh1Za+vQaRmJYH5mnBLZ6cDFL0hBARUpNKjapXciAFi6BlXlz9f1GjRItfPN5n/BJZdU/o7DXLXJingJszjb0hJ8u0jBQkMX81jO6mqlyV1ixLdesnZpQGRKZrLSE2tM0NffeY0/iClCeMkbTNm4gi0LriLvpuS4p1U2N0U/0vImNNhZGPyx5yICVNiAdO+3fRxhCyunjmIJWRlAJGren7Cs8/nl/SdWu8D/T9hhgyLs3MvsWonhwDwU+sN0+Jp0iKDo+t1hGlgNrXn6YjbbvmfHoPrRvG+YgQipf3d1zvHlOE5zxW1nUMmdWwom1WpKQI/oNt25lV+4j1+lv4mUPP8/cbvuFR4bYrFTtRCsKPiOQQoSaaIi2pXyFXdf3/QeV0+OIX+dKP/Ai/6o/+e4wJdlLWQ0tpSrdB7T6BXk5M7h2MtSyu2jC0rmbiruuZ3UusvoKSmZ4fKUtAfcBebhpM22LbvhpQtcKoL38cUkj85P/jL/Hw9nv8C//+v4VsTVWnW0O5+MZCcCxu5Dg/cMye9dd8HLu7oWRI8Qgi4cID6SKOvD88Y2gfcXv1Sd578TNkFM57CAt9v6FkydX2CiEk0/yKEM/YRtOYLUd/z6v7d6jxPYZlGfF+4nh6hdZHclnQSiNQpBxAlNq+2jcudhJFzjP3D++SYqHrVqRYEGqp7HSz4Xy+q9yfYng43JPSTNetWJaJ01RJqlIa+maLUeJyEZ0JcSGkA1Ju8D5ytX2TkBzH8wPaJEJ2TPMJfRkep1RY/Il1fwtCM04PdM0a78d6ELpTtT6JhWUZSeKMkDXAQ4jI7N5l3b9BDJm0PFQqgK/0hORnjudnaKWweotzVe4iZQ0L0OaaoXuMkILZ3zH010g6juk503zkpl1fAHHT5fVF2mbHEjzzdKhkieJpm57GPIEi2W2fcDzd03U7Fj/XjqnfVUO13KBUQ8kZf7HxtG3zlR9KWg8UIZjdAaUzpWiSC3WFbFoWN9PY9uJq71i1t9yfP0+IDiU7YgxVUXtpCbqm3j4pV7i48zNSyYsuZINVj2jsjtN8IJfnWNUBEWnnqq5mRSnVNiGFq5BzVaoB0WR8HAnRXQx/irZZEQgktSBFom962uYGF/Y4t6BVFZbF7FAqcz6/xDR1a+IWR4iemAPHs7xAqhLWbthsbrFmzf7wNpv1FQ/HWu635oam/2b+9pc0qtF0KXB+vvBiKly1inWrUI2BzlDMRYpw8qiHM2GXUI/WKFNDA37ie76Hr/tNvxnx9AlTgUEU9GX+JIRkvb7iE/Jb+MI7kof5syh9ri1EM+CDx8cRIXJlc58d/v6M8dWUaruGZthguo627bGmGqar+r+iPn72r/wgf+/7vp9f/b/9nTz5lq8jX3yAMTlKDlXVu5w4zAcewsT6409xKiGzJ6dCTIWUp0odVA0UxTjv0dLw/ouJcd5XhlKpFa1WDUVFUjozzdOFpa1BFLQpDH1PCInW3lwga5HdtgpVQxrReoXUDW45Y4yisTX4oaJ3ZvpuVf1jUmD7Dq0Mq9WOfKFbzPMeoRaMKnTmBoHh1f5trjaf5Dw9u5ilV3Rdy9DsmBvFsii6psekTIgbhu41xCDRsmda7tntKqcrxhlrTJ0zasVu8ybxPiBEPaC6do3zI6t2g5JUzrdpsHpAysRq9RoURSojx/PzqvOiw6ieVX9zaalqtZyyJwTP7uoJzo0Yu60G4FJw4YHRPWfobhjnIyEsdM0O7z1d1zD0V0hhq4RFKqQoFcPMgPMzLh7IObJePSLFyt8OAc4nLlawQCnhkrqbWQ8fQYmG/fEtrBkwukcIc8FYf4WH0nl8QIhMETMGS8mJZT5d2L2S7fpNjscHvPOc5T0CR86JUjIpVS3KB3aTTvYXDkyo1UZ2VRpQMtFH2sZSsmaeT8Q410gd2eDCAbeMJF0ZzDEGpGwoxdWWMQYOp2eVIlkSje2rP6mAdxNts2aaYwW/tx0+HLjfv0PTNijdM88BZGG3fsJkjsxuXzGtKiOzpDGGnCPNJRfNuRP74+cxcoU1lnnes0zP2O0+ge+/ls8861jfNry5kvy9v/8WT99Ys7p+jLaKRQmMqpYXZUF1YK4gpYwIgZgSRcDxrS/w9g/9EL/hz/055gGEKvzjzZ1AyMx2teWTb3wrn3lr5uA+hzUa50ZSCQigba4oSTDdJ/xDpBWSph2QtgGj0W2DtRat9MWrVlN4X/3cF/j73/f9fPNv+U7e/PZfSBb5ouh2xGXBzed6IC0HZguPPvUJnAVjFPP8QAg1cUZKTSm+bmWalvV6x3l6xe3uY6zUCu/PtG2tEJZ8pOQKdMs5cJ7v6ZpryAXR9DR6gygLp+l9+u4KiWDxE0IkFn+ixbLMC7atvjehBH5OUASNtby8+xxSCozekbNEWIlAosSWFBzWGhbnKQWKrqGR/bAiMVFEqa4D20LRtM2G0/SAlIJpfokSDUqs8eFMYysNlQsobugesxoesbgDpXhKETwc3wFRoW+pnLlefy3n8UBMIzEX1sMOHxw+nAj5yOQiRm6IaWboblkN1wQfGLprvKtBGc4dSXnD9fY1ztM93kUas2Oc7i9VY0Pf31CShyJpbAfCc5reBxIpClZDW4sAaSjU0YBWHeTINB/YbB7h3YLzR3IO+KDQyiLl8ZL3l/Au8ejqkzg/cXi4p7HXCGnZDjsWN6JVW3lnX+mhpFSDlDXquDKPJbfXH2P/8AJKz9398ws1oBpuT6cXKANad0zzgtQZoyTGNkgpcf4EFIzpmM8PGF2rqVwC07RHqRZrW7SSnMb3yaW2d0r1Nalz2rMsnvXwhJwNp/Pz2jYLQd+uEKIhRSp5IExVterHCu0XgsndE3xgu70hxULwHqVrKsXij4BmWWZK2aNlT2GhtYZSHDHVyCbT1GRTawoxHiozZ+hw5U0+81nBa69v+cSt4dkX9lzPZ77m0ZskqZiLpCkCmQqKCjUsqm5zhBBI0zCfHHlJ/Pgf/4/51L/6r6Jub2mBATAXj9yXv2qUUN+0PO7fIKWF7XXL4fgMFx9orEWyxvCY126f0D02SBamuxeE8x4pIo02lREuyiXOqbA8HPkvf9//mf72im/+138jRUL0Cz6OLPOR8/mBeTlz7w6IqxVPP/U1SNPQa4Dq/ZNKVJ5UMdV8Kj0+7kkJrtaPmKZn+OSJ+UzG13a8vcZ7x+LrpdCZ11mWCa0UwWd8PDK5PX23o2k23O0/R9uscS5BaclF0g8bnDtcdHC5ZuTlQikOIQNQ2/XFHdBaI4X6MHLrND6reGVhiCHSNFsm9xZ3+8+RSwSRmZcRa1aMuq0LiRIribJkQJMXgRSB/cMXsLZn2h8xuiflGRceaNuBnOq4oAayfsD23lfOuCy1bSs9SnakdCbnzDLP5CbR2VucG1GqUEpkmh9QynB7/TW8895nMLpjXuogOvqJ3q4wsmcK91itaPWGwLmu5KNCSYcQAoGi6fsqv4mRh9Nzbq4/gj+dSQRKmdE6UlLEmhqLFqNEaYMSFh/P5FiwZsXt9Q3z8pLWbln3O/an53V0kwvzfKJp8qVj+goPJQp1leqqnyhnx3l8p2aKq3zh6lR/V0wBY3uMaVmWBUTByhYpE87NbJqrylwpJ2JKpFxRt5RSoVFSsiwPyFzZLSVlXBxr9VAKLiTm2XNz9SaLv8f7CYmgtQNCdngXsUbTN329sfQVu/WW+8MXySUTXUDIqmWp2WIdh9OezcZUTU6Y0HJDa64xsoLaXQg1gWOJCHHCJVcPwOYxx/EVfacgC6z+GPevJI+6jk8+aQnTxPzZz/HkPCKXCR8bLIpIoUiBBURFIaIuLVmYHNP5jBoPfP6v/TX+e3/hL1JywQpBI8X/z42FMoYnV485n97i7sXnQccKfCuZXr/G09tvY7vq6wq7FATfgF8mTs+fER5eQhwhh2oNCYEf+eN/Brvq+RX//v8MZTXBn5mXM+dxzzgfGMcT+3Ciee2K3RtPwEiktsx+5P7hHdarm8ptKoWuG6p/yx9QUpGTI6XMsoy0/UCYDD5HdMdFQT8hRMHqFTGXCyyt4JOjiEqqiGnmcHwXY3piUDRmhbUNx9M9SiSUbEipomesaVnCgdntEdSsOyETu/UVpRS0LJyndxFoum59aUkCLs7EvJBzqu2u7klFkkVCCsFxfEnKnpiONKZDanB+obE3SKEv32ek5MRuc815fEBeaItSKaIr9O0ThrYy7Q+HZwzDjqF9jdP5nhRC3eAWTd9eoaXB6AGBZskjmYQ1HYs7Y/SGECf6wdI0a7RSzEsdiyx+IZYFawyLm5jCnr4ZcOeJtm3J2V/mumu8XxDUWaLVErfMNM2Ac2cSe5RJzEuF8VlrWa83xFAIwdOYFU2zwfkz83LAKIOQ1UXQ2Iacl9q1tAZK5HR6/pUfSkrB4u/IlCr48gtSZrTSOH/R4siKvTi8fM711Q1Nk6siuIAQuaplG41Pe1q7qi8k3WOsqJVTseQUcVN1dGfnyUlfaIcd1gw1TcK0SO4qlziPNM2GdX/Lsnha2yGoaNL7/R3aGJrV9oKknVitn7AsI43ZApmha2uyiZL4eML5E5vVY4JzrFePmKd7nKtV3bp/Sqsf83D+h3WlnxtW7ccY0z2inBFiQKaPko+ZT33DDZpImE6sDy/YxYBwJ0JcI4qiZImWBaGqWlIBQmZEiIT9kZvbLf/VH/4PePqt38rm0S1FygsKrn6Jn1cqlQ/wD7JgtlvefPJpzu8eOft36boBxUfYdF/LPAuCm2kazWrV0LWKzq7oNp8iuY+x3L1kef4uyh340T/9Z/ni3/w7/Jr/w++if3yNCyOzO3A83nE+P3Acj8wm0by5Q18NJFEV3M4HUon03Y6uvSbEka694nB4UWOqkyEIh9ErwLDbvEmRlZNFsczLA7N7SYyhVsFFA5fUDNUTU8WltLYOYUM8V353mqpYM0usLTRtRNITI5xOdzS7LdZu6foVizvS2B6lCufpdNHYZbQxODdC2VDjmUBIRyxnOttdtk+eEBNa94zLwyX19opSWqZlZOjXNfK75Jp+ogRKQdeuuD+8TWPqDOtwfknX9SjtKUVyPp9omoaaPtvycHwPo3oKmlf3X0Sphr5vcRcSa+1cxMXbV59PbTIhnkA6SomkWEg54dyEVDMhzh8ymIRSeD8x9NeXQsJXU/L0QGNW7B/eJZWAkTdItbDfv4OQ1Fg0kZGiujVKFjwc9ihhCMHXrbesYZ6Tu7vw8iNSNuRSkT8pzyjbEX1hGG6+ikNJSqxc0TRN5aQ0K1KKhJh5dfcuysAgFIPd8NrTj9PZjv3Dl0BEVsNNFUWGDLJDqpoTJURDWKbqGE4jtgFJx+31xzie7i9zhg0IT0wTzp0xSiMpuOWhmhHNBqEj43ykZMH9wz0xRFarDX2/Zl6OnKf3sWbD9e5jzPM9KedKs3RnjB2Ywz3WKKKbmeZXpJgYultiGgm5+qiMNhzHZ4iiiJcoKYrhvLwNMhKioO8+wulZ5ulrVzSDrshQlbDrymXObQYSMVcFtRAQcoYkLmjuSBoP9OuO/Ttv8TP/2X/Gb/5P/wxKX4BxP+9Q+vlfHxxQpUiEtLSPXuex/wUsr84Eb7nafprGXCNUjdIOEfYPgamJbNcWayWyVejX36S5ueUn/+T38pm/+jf5Ff/ev8WTb/kGxvmB0/me42nP8XTkuBzRtz03X/MRIpnW1q1dDFBfiGXV1/ZHyjPOP3A8v892/QSrG1JeOE33xJi52j3i1at3EQLWl8tjs74lxsTD8V18DDy9/SRgcWEhhgNaiZpy03S19TFXZAJGr2lsi5aG4+l9hCgfDu+dnyulImWcn1BSsriFGH0NCvBnkJmUA5N7UZcf2uCWQBEn1FATeEgRhaRET6N7tNQsfk/fXKPNU/p2xTjdAUslQF6wyNVbKZld3dI5N1FEIKfA0BtKiZymu8s8q/rclAa3BIZuiw+OEBYQiiWc0bkw9Dd1tMFSB9upwgy1XBOTY56P9O2Gbn0FSKS03B3ewzaCxc8XJlVH8JGSDTFGGnNDo3fMJdM0iuAnxnGmtatKL5A9Q7+u72esIathifSbR9xuH4PMTNOxts/zQkkz2tTEk8nVJOmQNIgOpSJSfBXbtzlMXG0e1+RYIXE+1I1USqw3OyBjbYtVAyVH5vlQ50KmQQjL8fw+XXvDw8MDN1cfIYSFmAO5VK2S8DONaVmWU403SguN7em6NW2jL4CsmZIiqXiePPoU5/FMyv7yqOqLua/QdzURYvIPCNPRdDvO5+ekMrP4hbZZcR4PlFzQOuP9wnb95PIQWTbbR0zziRBHYs40egO52srbdsVm9YTZ7/HhBMia/utaRFzRKMnmZkNWkhQzRRnU62twB4qZIU1EaS6E0ZrookQhyoAIR8R8T9xc82N/5I/wxi/75Tz6pm+6VJqXA+if8TP6QHqppOLm5mO8f/8FjN1izbauZFEgRdUfUS+G+4dA10nWg0GqwsNnP8sP/m9+L5/6zu/kE9/x6/Hj2xyP9+yP9zyc7lnywuNveJPhtVvOy4HoR6y5ZlkuimppEAqm5Z4QR1KZUbJjs76i63YcHvZoo5iXhb7fcjwfcf7MzdVriCLp277qfpAM3Q1iPnM4vSSlTMgL2/UNUipO6W1Soua7hYAWLY2uuOOYPClmpEzMyx4pOmJcQNSHNpfCebm7QO0b1sNHiOkdYj6Si0ewYbN6A6vXHHmfEKq41zuPLwc2w1OOp7exjeR8dvTdQGer3mgc3yOEwnrzhJQkLRnvz8QEqEQpASUUm/6GUAoxq8sKva3pI/OR7WpHKiM+3VGkorMDu+0THsbPUXJCiZbFvYKyru6BNNfgg2ZHjJFpfMV2c4PoVhQ894c9XbNhu76tWi1pyOlM19ySE6yHp1h9Q0gHOv0am/UbnMYHSgrE4ADo9BprGm52H2VxD+zWb9QtXJp4fPsaQtj6nJ/ep2875qVaUnLSTJMndxMpRpwbaZo1OcA0jdjtV4HDNcbggmfVXzNPB07zi8q8Vg1Dew3AedxjddUPHU7PEUJgzZrVylCk4u7wDK0aHk7v0fcD3nmEgOP5DimgaeyFUNjSNBYpC/N8wJqOeb6/pFgobDMQfENrV7w6/hRXzUdZwpm43BPTmcPsGVYrfPSsh1tiKnDxK1lrMWaFcye0VrTNjmmaOZ1npCw0zQ2Li1i7opTEvEREqQ7sZTlzikeGvsK9lsWz6p8giqTrHhOOin67Rhp92QAWfM6Imy1pjJTTjHFH4qojC4vLgkYXkneI00vSs3fQRTDuD3z2L/wlvvN7/1QFu5UK+a9nzn+DBlYARdB3A4+vP02IPVJ2iEsMuJI1NKD+MZKCZfIRHz3y+Jy//O/8O3zqO76D7/hD/ye8Dzz7sWcszrNEz6wDT772E2w/8ghjdvTrW07jK5QStJ1FCA1CglA4N9E2K+YlUzPIKtN6t3sd52tKsLposa52r2GUYtU/Yp6relsIQy4SvRrqQSE6XLzD6A5Z7CU8coXSQ40PMqJy3KOkbXuaZmCa7rHCYJqOGu9lLtuxjFTDJdFV8/7Lf0RjB6bpgFSVQ71Z98zzA41tcfOBeZ44T/VALfg6vwkn+t7S2OuaVIylbwZmP7M/viDFwm5zgzYNkzuwzEe6Rl/y03SdNeEZhuEinVhQcqBrnnAcv4iSks7egoDF7REiY22Nh1qWmvxMgUc3H8OHGedGtDF03YrT+FBDRo2tSTNSEWLEGAlZsxlex/tAzpacK6dcskIbcPEdVqsGSo+WCp8eQCa2mxusMWh1zcPxHilLhT6WQIgHHg4zbavJuWCNxXlz6YpmnHe18pwr19/oCnA8nu++8kOptVum6YQSZ3LJ3Ny8hqRlnKbq5g+BoXtSJebLu9i2r2tXdeHXiIKUEaX6ilD15cK7EXTtgBQa544s/lhvMAGiWBC+Ru00DSu1Y/EBtziwe0JwGDXQd2uO0yuaxiCSZbXaoLXCqB3r7nWcO3EOLy6rz8x5PLBePa5rLwQ3N49wrgLghKwPlG4s03zGmI7FnUipI6aENZr7/fvsdk8uw8yWnMCXysBRTVXZlpTwMTDHhGkGpLokq+wPSLGCde3rOT3gPvcF3Kv38Kczt/+tb+bH//gf5/Ev+aVsvv4X4EOiMdUKUhnRdVX/zyqZpJQUBI9u3uThUEmFWkv6VtEYUEpcONCQUsEnwzIF/vL/4t/l8KV3+Ff+xPfQ7HbYXOhf/xTvvfhZFuO5/thT5FUDFBZ3wnlPYy0pZKRs6s/tQvCcplP9b7RY3VUcbT7j/AGtG7peEsMERdJ1dcj7cv8WUhTaZgslEeJE12wx5oZpeUDLmkkWwsJm8yYpZozQyLYhZYHRipRnzuMDpUgau6FtVxdj65mQJ2KsFWo/rIl5ZBndRYtTM+0KESEd94cvYVSDFAZhBHO4IxVHazZkESgycRrveP3pp9kf32dor+ogP3hyyUiVMLqieaSoW7+hWxHD4cJSWhPdmfVqh1Et04X0uF09urR/mVY/YhoTUisWN9O2PYodc7inbTuU0KQcmebKqkdUnIg2DTmri+XHIYVlHENNLFGmEhxiJWqUElnckXm5x+iO01i3g1JYuuaa1fCIadaENLK4E+SZUtSFybRGFV2Tf6OjH/rKBdMNIUDfbdByhxSW4/ndGkTQaSgt6/aW83RCCvOVH0olV6dyiBolLfN0prESo2tKaNdVXreQhdZuLmKqhQw1tyzvuNo8pe8qSe902tO1ld4Yo0epghAdT2+/nsPhQNNsUAp8mNFqhSxrrB4o5UgI1eXctg1G91XBnDyaDTc31xzPB8TlofPxSEwzTWMxWldZuwyX8EvNcTzUtlN3lFwI/lSjnpba7jSmucwgDC55TN9SEJRkSXEiyBlKjy0NSVT0b7n8M4RISZJsWvLasBSBn464w5GroSEsiff/qx/F7mfy4RmvfesnefflPZ/9C3+FX/kffw+Ouv4H8eEwWwhR0bn/lFPpy7OlemZ1TcOoHUpr+lZiDGh1oRBcfrvWEhMiP/FH/wMefvon+XXf+5/Qvf4xKBkpBJtHj/HrLa99fEfRicWNOFdfJ0gW73DuxLq/qWkgUpMZESoiFWw2a3L0xOyRkppY0gzsho+xGz7Fe89/isKBzeopPpwpJBqzZppPCBFRKrMse0qJtHZV6RTZ1RW+7fHeoXVXE12XE+v169wf32Ld37AsNcqoBjJMWL3DaiilSj+07AHFG69/A/PiOaS3UKaSGXMpFSerG+Yw4vwDtmlqJlvJuHjCth3naY/RLakklnkhl4XFzXTtlkK+CHg7unZLSp6r7SdYlgUfI0N7UzU+MTK0r7GEA9asMablfCpEp+naAaUt3h+IsSBNqUm8Wl/M7PXzlpLEmCuMrsjlqvUrtXoUCiFLtV25hSw8SkmM7DlPLy7GdUlhQSqFMYqh2XE6HzieHZvVDc6PNGbFqn+ED66m3lpFCJFlXpjdxNDXQ7xarlqW5YywDqVNNeRi0crQmg3WDvQUpOq+8kNpnO4uLBXFvJzYbm55ONwhZCFnydCvOZxeIFVm3T/hbv8CrTVNY2magaHb8nB8wav9l7jaPGK96kmlOradn5mXewQS51LVcGRPKYq+XTPNe9bDa5XF1LRs1/UB0NqQiyIXx6rbcbv9OCUHtDwQkqft1mgJY9zXdlDU5IWS5mquJNSHUmuUgphCtS4oiTYVlxqTr+yaoln1prJzrK5M8YttVilD8IGS9SWosCYeilIbJIGGYkjGEjeCl3cz53fv+Om/+9NceUF3OvOJ1x+TfsEn+dn/6D/k9tt/Gdff+K001lSMsBAfCiY/OIo+3Lj9vMPo5//75VtgPWiMVShVkJcgyX+yA/z8X/ur/NAf+P38qv/97+NT/8IvZZpTDVaQhaILjz5xC80DJGjbDdasWfxMjg7nFrpuQAhwYUaTETmjZUNjBmb3AqmqzaNkyHLhML6PFrZiWu0IijrYvRhyc6koXiHa+sBnjyjVNOwupEIlGgQKH84ICafzS4wx7O/nC5JGAhnnArapiRnjfHeB3UnaZospAy7PpKQuSTWW1uxoTSWFxugxulIvXWjJxWFNA2RaO9A0TxjnF1izxS0Tq+GGw+kZSn1Z8+WWibZpGfo1iz/jfAIxIJVHyo4UKgl0Xh4wpuE0PdA3W1KWtWq7xDv1/QotK/iuNVvO4zN8fMBHh1QNSnWM4wkhC0atyKl+NltbE0W6VYdbEkO3Iee+YnnanpgmvJ3JuSCF5Hi6p7E9RgWyqMbixlwxdE84nl8yOYc2stpIlgmlW9pmVdNXtKE1a2J0PByeXQqViXG+J+SJ3u4AOM7PkMuzCgBM/8wz6Z99KFkzMM8wjcslldRgTUeIZxpbgWg519jk8/gKUBdtwweGvUDB07SacbqnUS0hejp7RQqpbtqavsYpp8Jqfc28HPDBcXP9cQQCIa5qmm6cLpuNhVQu6Q62I6SFZT6CUPS9qUPD9WvVVOjAs3wYJZNiqEPPVCg5kYhoVb1is1uIeak41Agb+ZTG9pUd7iZiGesDJXWlOdIhTINLilyoOAhRyxWja1SSvpQozXrg1Zf2/J0f/Dzf/gveQMuJgZbu6z/BeX/grR/4Af6FP/q9CGXICHyCVDK6FBqr68jmnyySCpSL1kl8WFUVpCx0nUZcKAT/tJ7vvR/9Uf7y7/yd/Irf83v45777u+vsyWYeloWcHF989vdQ9sS0HGhMg9YDp/Elw+oa2wxc7Z4yTnfE5BCivn4tDEUkYgqES9JqKg4pGrruinmeSLkwuncxpiVc5ikPx1f1lu6vmeYjfdPwcHqXD6LLFwfWdIzjEZgBgdamWla04Wb3UcbzHSGfWdwdi5vYbt7geHpOY20FrinLvJyQDJUVpSSLf2ByR4yxKNlU31uZQURU0DTNQCtbKCtCXLC6pek7hEg4uQYixgrG5X2sbWt1NU/sNreQK2q3ziCPlNzQNbZKHUrmavs60/yAbSyLX5BSc56fkzNY09Op9eX7uuI0vuJ0fsZ6eB1EJpVC3++439+R8gOUOuboO0VcyodBjwKPWxJdc0VIMwiJ7XqW+UxME1LWFORpPtC1K3bbW+73b9PYNda0TO45OE0Naa+IXCUUSieINRig6wZO43uITqFlBcJBZpzuK3mzOEI6ImXLw/ldtsMNOSf67quQBJzmPZqqpjbSsswnjGpwbkQ2mmmp6/sUFRRF3xnm+VBjqnWN9Ak+EmON7NZmzeyesT+8jw+RxUWQZ6S0GNkR4lL7TWlYloX94S28n7CmZbd+jNGG/eldcolE75H0lCQ5n+5QSnB1dYuSmnk+0rWry2GnabuGednj48jQ3aJ0JOFQqmV0Z1JJdP01p9OLCwI2kbLj4bhHCstquGEeTwQ1I0WP0YYUa0tQLpExMVWNixSFxkiMroiIQuGdlzM/9pk9/9Kv+iZuBlg1j1kNDUVJfuaP/mGuv+0X03/yUyzLwlwKRim01qxbgy2ZXMSFwfTzdEqUf/xwolyg8HXufIEz/X99ueORv/jd383m9df59t/x3QilCTlxmj0v92+zf/hpJvcFvL9nt7lmf7pD6wktO07He6BU1rLpECWzWt1yOO45TzVcwvkTUmj67pb94UuM83sM/U1FDeeZmC4zoOkVRjeXWZe8AAQ9oSgO457d5hGLW4CAVgP90LMsE1O6R4jMZvWYlBz7h7cqX8tK5vkS7+NfobVACMNquGKajwzDBi0lShUavaktS56rebcAMqOoEWICjXMTIZ3JubC4I4+uP8b+4X1yidhGY4zleL6vF9h6y7TsaWzHNFfwnBYtpSx07TU5CLyfqgdQZ0qClARSaxqtEcKQykzJ1asYUiAvkdN5j5CRftgilawHq1KEGOi7DsEKF87V46g0HkVMhfWwRSnB4fgKYzWtvOV4fpfD4X1W/SOsbUnJo4Tk0e6juDgzLQ8Mw+4yc4SQ5kvST2Ic79C6xeqGGFIdZZSCUAklWwQN+/NzbNfycH5Ob7dcX73O4aQI8UxMZ7rOVsO3EQj5VVACrL7hye7reLn/WUQWNM0KH0ZmH7i9eQKppW06DuElWpkLba5uoWKIWCtRytB3w0VwuVBKw9Xulrv9HY8fvVGVsaGafFNKrPorYtDM80hjO5SytGZF190iSmHTS7TVpKBxIeDDA8a0DN0OIQxt0zCOZ4wx9O01Wq3ZH98ipBFrBrbr19gf3kHrFq0tJiWSq7lpXbOpwxlbkNKS0oy2NfGzt0/ws6frNUoY+tUV42QpWApUm4DQKFEuh0ImRvj8/cT/8x8e+PZf/E08fiTY9rYKKIXk/PaXePcH/iKf/v1/kON5pGniZQ6mMKo2gS4WrBZfXgT8vJ/PB83czz+qxIen0j/+JYRgORz4S7/jdyC15jd/3/fR7q4IOXF3nnj26vPc7f8eLrxb46f9fPl5bAgx4/yevt9SkkEVR9U3NKRgmOY7YsgQYuVe96LKL4r6Msc6B7pmh8DWS0u2KNlV1bToyEkgRIMPDmPb6nvMM5SMNZIYIzHNtM2aEGeOp+cVkqYzJIUWLX0naM2O4/gCY3oompQDq2FXrSAlYnVD8NWCIj9oJ4VEColtVozjiLX1vc0IZn8kl8I7z/4BnXnE0N9WfpabWXW3LHNknk8ViUNP0zS1qmsjPowIFLv1E+bZseofc5xfMLlTfehFg/cBKfwFsOaB64vHMiJVoW03eL+wpD1N05LxjNM9Q7vlavuEu328oKBnpulMLgWrNVLWSsaHI1XtVmjsgBDVBZFzIcwzrdny3qvPEtLEenijCl+twTRbYqxgRWs3lxltg5YSYyTH8R5Fc8l1S3XT52fsJcTycHxJTL4utkg0pqdrb6rWKX0Vg+6UIqfpPcb5gd32CZOvQY1SaO4fXlFKZvYjfber+NLzGSXVhzDzEOrD5NwZ9JaSBdvtE06nYxWJ+ZpQUjUU1cF+nh5Y9VcMasU4z1jT0A8bTuMzBNSAxmQIKTG7V+Q8MbS3NY3XH7G24Wr7GvMy4vxIVgUtDX33JpQaXSylRWtLLgJKiywRIWR9HZkL+D9yc/0Gi19qMkh/i96s8D4ilWVeAlL1GKnrRgPquhZAFEJKfOnB8/3vSvbXr/NezFxNmo/KxNpIjIh88c/8aXa/8Nt49M3fUlEi2tS1cS6MzjP7iFGadWdoC9UqcqmL0qV103zQol1G4T+vz/vHFOA58xN/4k/w2R/4Ab7rT/0p1m+8QSmFV4cjP/v2T+Dnn6FtMiVrrFUMw2uILDmOJ2yzYb2+prHr+h66lpIVsz8i5QOd2XByZ+bFk8uCaWu0VtfuLt4qS1zOpKgQEsa5tk2leBY30tgVrd3U7Dy5Yr15g+AnhvYJiEhOEghY2+K9Y75EXjV2R5ETpXi2m6/h7vA2p+l9pCxoVUhRYIzE+YlSEn274+X9S7QVFFdY9VtEqSSCgud4PNI2l9mMCizLHonA+YWnN1+PkQP74zvkPNTBecrYpsX5wm7zlOgNJVbigZIWraoafJrPhFAoOEpWeDyzO5LGiavta1BaduZNDuf3ahq0yhVG5xXzvMeansW/IEwK25iK4s2BkBaMsmxWa87LjG4KjW5IZaSy01vgg1a+MseV0szuUJniMeFe3mMUGH1FdBltFD4+0KkrzuP7NGbgZvdRDqeJ8/Sytr5j3bb66InRoXWFQRojsGpgcg/M87kamIEYa+aec45hWOOWr6JSklIy+hcYq0jF0diaF5WJVXpeJEpJrGl4ef8+1hhKEbRNR4wCYxTOjSzujLWC03jH2d3VYXUMGKtrKZgF/bCrqQxxoRA5jfdo0+KWE6+WA1JHpBRoWoyAeXEgMkqumS5O6RAd6/XXMU0PhHhGCJjmO7p+jTVrUhQ1oFDW9iyGiDWWFDSNXhN8IKYz280TTmONVNa6QSl5iXDWtG2LVA0hCVyoQkwpPoCk1aSIGDL7JfPFWXNIkrfv9iwHwflkOe00H+8im3Dm5Y/9CJ/+Xb8Lay6m2JKIPuJiIsWMkpqhG2rssZBVToDA5cIrD42GW5vRNeHry2LLf2IAVXLmH/3ZP8vf/gN/gF//R/4In/p1v46UMq+OD/zsF36E4/T36ZrI4VQtEtCidUEKzXb9mGk5YtQ1OWWCG0F4hFAgHFIamnagX1UFstKKabmjlIgUa+4f3mazviVFwWazwYcTXbtGG815vGe3eYSRhhAXchlpTVejmMRIStB1a3TbsvhXnM5nUgh0TYfSHYjIebrDqiteHj7HtNzRNgNSag7HV/TdNaqYKjgvhZLB2gZlagqL8xMCS0NLyZr1cEVONZdsXF5gxMB6veN225FjprUb+ua2Ejt1w+wfmKYTXbshx8DV7gn7/Uu89wzdDtttmJcDLta5pvMT19tb9uM9WkmG9tFFRV6QdISQ0apjWg4MQ6FtWrTaMS1HunYHJaFUwagbpmlkmk88nN9njg1Gr1GqJeZC166AC3LXVsChS2diWdisn3K/fxujW9rG4NyZ3q5IUdJ015zdW6TiiXmksQO79S3L/IDVgpD7qp8zhpQKTWOBwHl8jtEGpdZEXFXKi5rE2zSWmDQ5BYqemReI4Z896f5nV0oEtFBYWzPop3lP8J7bmzeIKRG8Y1lOxOhY9Vc0zcDD4V1O53t22yeVWKdapAyclyOTO1UAnN3hisKHau4TwmLkhhQfmOcJF2am+Yi1A09uPsZ5fMW03FcDq2qJIXGze5NnL79I18Hdfs8wfIRxvuf53c9irWVczjXxVSoycJqODMOavCRiyAgRmP0R5Q0pQ15OSClYD4/xPleLSE5IJAjJ5I+0Ta3omlYjlGWZPDJpugbICWQh50JKhdZahnPGPuwxx8x794X924Ev5oVvKiNvfu6HMFLTZEF86wvIzYpZaaKUuFAATd+tKV25IGcFJWXmDO9N8JmlcGUF/UawNiAu6/p/8kAC2H/+8/y13/27+frf+Bv5ut/wG8jA3fEFn337J4j551h1mZwyq9U1rb1CCsE0PyOkiPcn5mXEWFtnWlLVKjRM7DaPiSlxOt/RdR1aNxdiYcCFVwi5oJTibv9F2rblNO0pSbHdPK4c7GnPqrutYP20AIrFPyCFrCm/IuM83I3vs/h7unbDZvM6bdvjwoTzDkmPc5nbm6dY0zNO9+hG1+yxVGUUXXNFypUMqnSh0St8mCnMGG05zwfW7YplGtG2w8d91bQhCfGA0AoXPaYMKN3RdRvGaY81W2JKdYisrxinI5lI36+IyRGio1BquKofOc4v2Z/v6JotUnQM/RX3D+9BhN3mGtt+Ah9GQpzJSTEtB+YPkmdzRhlNI9c0ymBtPXiU0SQS5DMpJRp9Q2uvKWT0JfqpRp0lKIGQJoSUOH8gRo9t1sSYkWhG96UL/34g+EjTNtUzqje46Alhoe+uSCmgZKFkgTENSoL3/qIyn2jbhq55dPHdOTarj5BzZl7O2MYS01fBUzJkVsP2ohTNbDY1cTRlzzRN7LY3eK+qoM1YrF6z3bxRb+ySidHVxFA/gYg8ufooQ7/mPO5BnumHK2LIXF/dIKIhSMN284iQPJM7s1pfczzesxp2aG0wqsdHx+n8Ckh0vaW3HVPbM7sRhGFezih1xc31Gx+G3jX2op8AlOq4bt+sQ0RmcqlCzhA8iMJpvK8VSv+Iri11uyg15/MJYx0+RHya8Eky+w4ln9IZXXEOOZLiByW9Zycj3/7UslWOn37hOLw8c3x/5Nt/bOTpOxP/4Bd9mi/8F3+Hm9c3rD66w75xi91dIdueqC0ZQ4ialCQxg0iSZ07wo/eRn5kEn1oJPmYLnQCj/unC74e33uLP/7bfxhu/9Jfya//gH0RYw4v9c149fBYhv8B2NZDzBiEzD8c7kh4JOZFJCFlX8rnYGosUIykfERKs0UiR0bpl1W2r8VIIbAMkQfWtTSAkXd+Rs0fQ17SPnHg4PqeIxMP4ivP0qpIgs6MUyZhfMk0j69VjpJRoI2jlGqvXxORxXhBihQe6peqwvEsEXzC6I8eWR7uv59mrn8TYgFA1iyykPcHP+OUFIc/knLHWIbWolbXNZCb6YcD7EYHA2jVadnhxx3l8gVSKacms19ecxvuakFMKx/MzSsl03YpVf8WyVEJjygumaSgxIii0WtO2kr7bAIlhuCaEgIsTjV1xd/+Mm5tHhGVGipozaIwiXQI5Y3RMy92FMGEY2scIFFJ5olzouwbnIqvVwMl5UgrV/BwSMU9k7sgpAQpjWvbnlzRqoDENbdsTnSflxDyPODfTtyuGzhDpKN6R0lKzFxMY0+NDpKDpVitS8CiZKGgeji9ZDbdoLVnczPH0gqHfQlFfXe6bNpJpPiKlZJ5HjO7wzteo3qau33MK2MaiRFtBVDLgwxlr9AWvcMJojTYtRje4cEYqWaNj3MLt7qOczgeMmTGNZl5mtFLcbK/RotAOHSktFWcRI94Frnef4DzeIURGasX11VNmd6Dvbjk8vLzc9jXOJZdISZnb7Zs1JttGXu5/iqaxbNY3BJ+RqlyYOBdRWs6ViBkjRjWkXJN7Y6jajtPxJW23QpXA+3eamOBmXeOSG23J/x/S/jTm1jXPz4Oue3ymNb3Dns45depUVVd39VDd7o7deGjLMRgTxUCQIyMZAQaCEUIkfIgiyyJEiGCMYlCAKCEOAUVCJIrShli2g53YaTvuOHbbTbvdU3V1DWfc0zus6RnvkQ/36lKE5EKq3l/Okbb29L5rPeu+///f77piREl4utK0NrOp4Got+Gir+IO/mvjDX4/A7+HDaeLn/In3Pxp4cX5ge5xpn/WYZxti2yG3xePlvEZr8FnytYfI37wLKF1zvYMQMtMc0G2ZLv3nJ+HROX72T/9p5sOB/9q/8WcRTcXHrz/lzf7vI9QD03wmVZ5xnLFVhQ8TYTjRNDUxz2hVl3KpBEFhVUWgbdYFD5IiiJmuu2JZzhQzh8QIwc31OzwePsUzXAbODn2JF8TkQVYo1He4Rw/HO242L9BSoXVbunXLiZBGJrfnZvcFvIsYXdC2UiTqeo0SPc4PJaumJed+IqYJqz+lahUx9xgjsXJHiEUc6Vyk1ltW62uqas3b/cekKtLPd7TVLf0wYExLU3cYtSbG8J1NVAlSBmZ3RklFpVcYUwwpy+IIfuLhceRq94xxLgNoZSy1bZiXIzEl+qH/zluvra4QRhPjhPOZ1WpDCJ7JH9CqBDen6UxddSihabrSlnB+xoWFtr5FKcU0DShj8SGS6Xk8PCIEKC1JMdJ1W5alQQhRck5SUNs160aTYqJtrsssLXQkkUA4FlcEEVp3KK1pqroEKM114ZDFRFdviTngwkxlKpyfIMXCK/MD1lakPLJatQhRNG05f/fa1Hd9KAlRoVVJKStVsfi5qJ7Fb0ogPdpIFreAtqxMIs0D0/xAU79L13W8fbi7pFPHS5espHxjKkNskVOR6gEE0LIhxAXnPNkkAhV+mVFmIiRTzChhZr26JcZSL6iqjq5+UoKe9YquviaTOfkHtBGARIqax+MdPu+pm4rZDaRlYLd5j2E4YKwtX8BYCHpKSg79I7vtDVLCbnWLlBZqQUyezXrDaRCchj1BVEgiq9YSc8l2SyHRVrBRma9oxfubivNVpht+jih+AKE1/NT76C8EPnk88jCe2L7xPOkHrk+B1XuZql1BjrgYMSnzyfHM//uTyDceBf/YF+GHdi0meJQoxeEsKMwkIYje8zf/1J/i1//8n+eP/sW/yM0P/yAfv/qMTx/+M3K+g5gIyeHmGYRg8fE71xnnAtbs8OFMygOr9l0ENd3KICgYkBgUXbfB+4lxORYcqveXAW/D6fy22ErkLeQIOZbmvO/xwXM+nXj+7EsIJOumQmCxZk1OqaSYLyaSutGs2yeki7wyBMV6VfAoKSaMbZBKYivL/nhCoNlu1rhwIGdH01wXMWX+EJkbKrujqRLzfM+pf8mV/DJkxeJPrJv3aKstzpdyr1sCwoYLE2oq5pSLpUPGRGVLEvvcv6XtaoxeMc1F7mh0R0z31FWLSAKlqwt6JAMNu+4dlvmItavv/P4xZ4zJuDDRduWD1blApqiecpJUZo0UBZRWBtYDPmTatvQ2rbnCLX3B3IYjWnf0/YEUPJWpWfyRlBeGc2C3eo5AsWqvcWFidDObzQ0uHmHc8u6z9+mHoiqXEpIwdNUL6mpTZnm2uiT6M21VlVS3VGjbkPIJpQXDeLjA+Irgw7tE17Xf+0NJKoVAU1dgTM00P2JtzTgObNfXDOOCVDVGCxb/hrvHHqWhMkXyWBLhgiwiggqZarLomV0PF4D95B6pKkNKsgTXlEKbGh/OKNmgdUPKZcBbW4sUhu1qwydvvkFdtShZjrRZR1KQNNUG7weQEaUN0+JY8p5p2ROTZ14mlLohhojRNY/7l9RNRUqCcZzYrJ7h/cIwni6pZUkIkrpqmacRpUtKeRwHhsGx7Ta8Oh25spJVpXDek3IGIZHqMnxWEvXJRxz/jf8Lrw+f8Tf/Vz9FWq148lMr/mBy+OUGt2SW2SG8K/dvZQlDxSQDlZt4nAT/rw8nfv6bPT/caH7f1ed4YiL7hzsWqWif35TWLZKcMx//7M/yd/+1f42f+pN/kmc/9qMcTj2v738Na0fmKbD4mZhE4acbT5YLddUCZTOpVYvRFefhDUatGcYHhFoYpjNdW5L58zIhhWZyBxa3UOkGa0olxodCaWzrG3zocX4mpsi+f4M2LVVtMbYix0wOmqdXlyu1LB8iRlWsumtShmk6UdcZrTYcT29YdVdM0wykyyC1EDy7Zou95IeUFiw+4XAQy5xPqlJQHue3GLWmrlsiPVolkDU5pTKkReLjGX/B1YLB+xEhFefhWDhE7Xuc+s9KbzLsOd8Hdpt3qKuGeZlZ3IAUCqUSlTZkWZGXe0JQF/j/ubDks2CchnJNVRYfi/jS+2IerqoVSlQ0jb7k8ipCeEuIHucX2nZNiqBNx9j3pHhPvzyy6d5Fm46UPLYqfPJEADzWSNZPnuPCjNaCeek5nN5ibcncnfsHVm1Jb5fr18DiTtS2IwTL2b/BhQEpqxKEDQFzMcggFTlLrF4VO45MRWxpDLft+0ilGaf99/5QOvd7atsVMYAUaCk5Hx8RStNPE947tt0TFufomhskhhAH6kbTT3sqW7NqS6J01T1nGiaUSjgX2axvSFHiwkxMmcpuyNnQj3c436OUQFysucP4SNftCGEgpXTpaEWsLVjS4/HAqr1hu3qPw+kzlqWA3pQsLiwhDUJGGtviw1yyctoQ8kgWDh8905hYt1cEp8hBI6VjGAecCwgpmeYASZA4FbyvULR1pPML1SlD3uDcRE6ClBOpHDVLFePbH/KN//k/j2gqfvBP/4u83nYsCT4vl0IpMAm90QjRAEWukLIgXobXLsDXHvb8rW9MbH/1Y/7gH/gcX1g7kndMr16yqy3p6RqBQaTEy5/7Of79P/bH+Ik//sf5Hf/MPw1S8vbhJUt8SRwfaeoKnwUqpDLrkYJN+5Rh6jG6dLtc+IS6all3zxmmgeNwRBuBkpp+mFCiYowjOXl88gV0r1aQiqhS6vKCnN0D4zTgwoxUHSkkpAZjJI/H3yiF6WSI08Sh/zZ1tWG3eo/FDcxuQSlB26x5PL5itYK23XEe9hc3neXVm2/TrVbkCx9+nCTIwDxNNM2mGF2MpbIbpMoXS8eIumixXO5pa8M4T6xW10zjQMjnS+etQcliinHxiGGHEoIoMnf7l5A9IlfUzRVSBvp+z6bboZTgcP6Eri3dSucjLh45nt+yWV1D1kgpOJzvsFqWoGz7Oe4PHxNy6W3GaKgM9HNPjIFlMSghmaaedrUCYfGp3GDOp32pPOVMSBlJVbbO1S2LG5jmEa0rjIXFZbRUNKZlDo7D6RGtDeNyR5aW6QhCtmRZ83D6jOe3nyvORBIxTkyXZZX3CzGW18H19TsMw5G6vuI0PGJ0YtU+Yb4UqkMs38fZPRBjKWN/zw+lECaivgw7ZUSahlpVWLXD2pqBtxi5Yj9+yv70KdfrF9TNhv35gdvrD5imPWEpRb3z+Ja6Nsi0KgHFZIDygnO++KvO/SNKayp7RWUapuWAlKaUOoNDX/Ag/fQG50fm+cB2c8N2e41Whvv9byAU9NMdOtQlBpCgshWrtiWngHNvUKrHmo4QC8VgWkbq5pqmukIpwWm4R6rI1fZdfAgM4wFrBMLA6XDPi+ef53h8ixCZxmjeverQnJldTby402KSTIykb7zh5f/mTyFWLR/8yX8Wbrek4YyfEpOpsBaUKn4tKQSZBakKutVgSHZhiYlf+PY96ee/wU9VD3z1gy8ihcedBuzwgG22eBEwn3yK+D/8WR7+xs/w/Ad+gJ/8Z/5ppFLkDE23ZbwzSD2Q5olMxeTGC9bY4FzEO884vkabBq06QlyIXrBqd9w/PnAYH3myfcoyD9g6UemO4zBhq5ppWKg3Bqk0OUeCk6gKzud7bq7f4e3+E7rqPRaTybwmU5Rb5+VI21whhMaqm7Kh0TNvHj+iqjTr9grnPQCHw2sqc0XbtBi94fHwMUoJvJ+JcSw1lbbDzb704HKHUrrQIKuE8xEhPdoWXK1WEbJkcom6ecK+39PUa2qxJoSBjCamfInDbFBihVGJlFu8H3ly9RXOwz3LckZJQ1XvcEkQgqdtOoaxR5sW7w/E4GmrG4iaymAc0qEAAGApSURBVD6hH3qapmKc9tSq5s3+G0WnFB1NW5NiwLkBozXDPCPTTGOu6DbPQQRIikoLTucDPjr68ch28xy/eOZlpm0bUj6yzA6rVxhVkUOirSq8yzhfM00DbfUUqTLOOpRyjNMddaU4nT8hOjByy5helT9TJqTO+LCwuMCqW5Fi4Hzas1k95TSWXFMhUo6EWGo7xtSXiEvFPE+kdP4tPJSSxyfHdL5HmVJzSDHT+5nG1mgbeLv/FraqaVfPi1F1GenaJ+ArjqcDbVsRvKJrbkjZcz6/xdgSXMwpsywBYxqcm5AS6qolxkDXtfTjKzIBsiYFw6b7gH55YJy/XXJLCIbhSNt0OHfk+nrH/f5TKrPj5voF/XQmxEzwnqbasj+8oa4b2nqNloqoBSFoYp4JYSGkATfvqSrFaZzYSVjcgZQHxiWUFWotcP6EkIHj+Z6YBE39lLAopnmFC5BE5Be+79/noyd/j3f+6sAHv+0n2PyRf4JlXSHOb5kOZ/qz5lw/YWsqZM6FUX15oGmKQQXhMb7ib/ziW371577J7/n05/m9f+R30W0MkxsJ4wFpF1wjWIaeq//1v0T9b/4/+FEh+Mq/82+inz4FQJB58eQZIf9evvGJwoWP0VqSKTzpuuoYxj3r7hbvA6ayxJggZ9r6mtqseefJl3icWnarFaHalQxR1VLrK6ZlpLWepv7NoXCHljV13ZBiYhgeud29y/3hl8t1K2xZN+/i/MRms2GeF0JY2G0+YJqPjPOJtmlp65bGrHg8PpBzprIlLxRjJARXslsS2mZFCI6uE4Bnvd6iRIeSCudmwGLMjrgUOcSquSGmyLwcSCFgbEs/DiDTpUB7oq23rJst43RCyYa22xWj7ek1KSUqtWLXfIHoJfvxjrZe4X0B/y/uzDR5QnKXmpAjxsSmfYJIirZ+Ql7eMC89UgnGaSZFLtZfwTT3aGXJKdHWN4RYHqIuDJhao2XFqrthmI8czp/SVNfFGhMSUiqsbdl0TxmGsUhjz2+42l2TosIYics98zBQqRopDT6caJs1w7TnevtFpJQoaWhunlCZ8j3MItD3PevVFu99CZ6iqKuW5Iqow+iGtqk59yeWecD7+aJgEzzsX/PiyRfp2or7/cff+0MpBjgc7gtX2DTEEFnVV1BJgj+x6p4yTQ5j7OWOXOOWxNPt+ygkL55+mTf336SyicUdAc16dcvxfM9mvSZnkKjSskcULVPQFw1TRdvsSCiMMqis+dztD/D18y+WFKnMjMtb+vGR955/BSE1iz+RcySmI+Mk0KJmVTcgPcfzK4SakLKsZudlj1QSYyy4AyE5Fl/eUEZ15DRxt/81KlsjZGTddgxjqQ70Y8aqHavVTRmGSg25Zzh6hkmxX7/kF9//8/hqZP6f7vjSz/w+5rTgTyMLI/PrR/qDZVjXrDtF5AKGy0VrE2IsnCZh+dvf/JC/9Z98k5/88Ov8zh+2dD/4jHMYkWMkTAeMDpxfveTDf+cv8vSn/xy/GxB1RX5yjU8eLTUKhZHwwdPPo5Xh49d/nxzv2K2fklPg4fQZGYfWhvXqlnG+Y5p6Vu1zhMgczy+JaabRHr8MXG/fQ8kGRCa4xPObircP36Krm4IMIbH4GWtqhHh6ERo2qJ3E+5mnuw8Y5wcWd+Lhsadp1li7ZpnP+HjE2gqtLdN4wC9lU2XEisbsUI1AG4U1BqNf4OOZEDw5R0QWtO0tlV0zLyd8PLFqOjLQ2CtCcHjvcdkzLz1tU+HwtNWO7e5LvD3+BsgzWVeE6Eo5fCkD+kykH19T2St2zZq3d9/gNP46IS2EAItz1LYlekFQlna9YRxLaFKrNWPumaYj29Vz6kYyLKCUoqm3PDy+RCpw4RGrN7R2V67/OiAwNGaHbIp0YVWV15z3nlN/RumKuq5Ydc8ZxjNV1dCINSku7NYbjuMdNzc7nB+JSTGPkaZtmCeHMhWzP5OSx1yu1FKKAkjMAmM14/yItRXTvNA0mwvJoGzmlLTl1xrPknzZCroZISwpJbJYsPU187xgbcPhdFceOvK7+0q+688+ub4lRUXdNMTkcIuja66xumJxBiMqgkpYU1HZNf34WbGEDL9BimVDt9tcs1qt+Ozua4CCKC/lzSKlTFGQEwhlWHXPUSpzPN3xeHhLpCcCMmq27Qt+6Vt/DhcHtrs1Ic9M80TdNexPr9ltnl5ohL8JRgtorWhbTT+dSFkyDvcotSpCwqph8ScUgnV7zTAdiSmSkmOcJ6pKkbMn5eWyDYS6UqUBbyraas3iDLWWCNnio0SoDv+4oA4rNo/vcrj9iO1/NDP/7/6vVP/YP4r8kS8QpjO8veP4WtA8vWVzVXIriNK0TkEQZEBkzdc/e8Vf+0u/xo89fso/8hXB9e//bfimJs8TOR45Pbxh/A/+Kh/9xf+Y/OI91J/5F/jWEmnffQ/zoz+EmR3eZFCJWiq0lHzu9l0Ekk/e/iLD+A2eXD/HhYWYLMP0GcP0CmstbdOiVfHK13VNjBLpy9VkdgMwMi+F4jguGRcGpkUjRDGJnIdHuvaKlByL81i9oqk3zMtMFq6gSpRFyEjOghBHmloiZUvKMPSHIsnUNVoVlEZGERlYliNSBbRq0XSMw2OJqIwOu2k49R+XB2LWuNiTssOdXNF611cM7vGSsSvIk5Q103Igi0BOALKQFyjK6Zurd3l1//fIeK43HYs7FQKr1uiYqdQtfu6RFHCcUQ3z7Iu2XjSlf7fumMYDLjywPzkS0NY3IMrpylQ1MXlyTmjTXCrWHoRHqJlpPpFzIiW42j6lH0/AQm0MOY2EDDk7pKjIORb6AIp+fGC7vqGp1gghyVGwuIX1quPJ7gV3j3cILNPysvyJfqGudwiROZ3vSjJfZrRSaGMxpuNwWGiq0ntzwTMtI86VuhAq4fwJpSRtd4ub5+JxXN0Qouc8vKZrfws43M3qCVrVTPOJrrnBbFqmxeP8QGU6qmoHWMb5xOPhI6QZ2axvOfb3PL3+Pnwohbzz+XQ5SkNtGnbrZ6zqG6blSFQTw3BEiYbzELnaXWN0y83287y6/xq2CgXjoBXr9TP66Q6lNKv6lquVYgk903xCCstmVd4EJZHcg1jw3pOTQKuW3foDbNUWbG3KaNUwTEeauqapdBmio8s2BggxFT6yAiULPnTdXdPYQrAU0rHMC1erd4j6GbJZ4ezE4UPHT/y1fwp/c8f6rWCefhr/r/5b2N/z46x+32/DP+7pXy58+K1bupuap0+LujzkVAbCWfEbn9zzn/6VX+ZH0omv/liN+er3E65u0WGmX0Yefu7v8eqn/zKRis2f+F/S/u7fSehaPmxqttpSG4WVCpugEgW42VAQuy9un4H4Ki8fI8P8hlWzRsprxuGRpilEx7relnmJ2/ObDHClytcgxKGwufWCTzNuiVjbknLJdRnVsSyuWC2SpKkq2s4yLyeMldwfvkXXtgjn2W2e83h4w7Mn79Of39A2NeM0c3v1HCE0ff+Ii3fkNLP4iLGGVbchJ0tOEyEOtO0KiNRVYB4z16sfYnZHVB2BjAvnC8JEE8OMFIqcNE19TQwL3sOcj5BKtaapVljTIKUBGZj8p2gtLjbnHoni9rpjdgEhIk2l0foaaxuEtJyHBySReTmhK4URpeqipEGrQqZMOSPFFUIalLLkJNl2z0kRum7D4+EtIe15/uSHeXy8wxpPiJ7t5gnTMgOR6/UNbbvmPByRMtPVtyVaYRXDeMbYhlV7W6pfpqVtNggk/fhYXIvTA8bC/cNHPLv54oVCocgCpAxE6clRok26FHxvOJ3vuL4qqW6IdLYBGg7HyGa9YVlKYlzLsoSal7eX8KxEq7rEQqbluz6UxH8eHPb/++Nv/fK/nr1faJsty7KwWd8wjAOIzDge2G6eAILT+ZGQCkJh8See3XyZcShzoWmeULIi46nNDcHNRHlkHAe0LsbWw/GRVXdd5Hq6dI/Gfk/bbCEbrDGs2ydkmQlpIecZciJHhdSqbF7ygkCjxJp195RpPpR7rqmYXE9VNeSgGJY9KUecKx2qulqhtSKEmZwS0zxT1S1KSs59Yf3MbqaudwzDkaYFv0BtNwgZ8XOD0l/C6WccsmI/zfSPD4xvPyT1b/BLTwqB5sOPCP/eX0FoBZ97wrfSlrfvfZkf/qkf4Pu/dMumq0BknMv8wq9/xv2vfcyPdI6r9zvSzXPu9Ff43JWk+dbXePnv/gVOn73F/uE/zOqP/nfIbVPa9JcHh8yCVmtqpaiE4KqruVm3rKWilYoqAynw8vCKtw9fJ8U7rAGRIUWB0ZZEYN9/RlVVzPNMU6/ISSIun5qFWhAKFqR5wjQPpLxQV2skHVoKZndAZI3SBh/n7ywqvO8LtjVBTBFrugL/DyekqEvDX0CKrtBFNeSk0cay+B5rVkhZs2qfczzdgRi/k88ycougYZje0LQrRrdnmh84Hh/ZrJ6jpMHFM0obarshplD8cG5CIVh1HS5MhJDIgNEtLpyKu04ltGzoqicXEqVDK8uyFI14Xa3QskMqxeJ6hvEeYyW71Rc5HO6p7Y6mWpHkzMPhFU29omt3PB5fohVIJFKDEi0Pxw8RIqFkx7q7pR/fgPDU5jlSZx4eP2LTPSNTog7Oj6zaLTFYrCkMqTkcy4ZMNuQkULLi4fAxVW2I0ZW83epdvJ/Yrt5lng8goJ/25OTZdO+hZUXggWX2WLvCuYW2viLmA0Jckt26wvkzQthS+J1HrrZPiWFhms6kDEpXkAXzMhLiwn/5d/xz/9AE5Xc9Ka3Xzzkc3hSVTcXF+pDpultSSpz6R9arLdpqLFe0TcNpeEPOCkFECHXBgq4IMSAv4T7vBE2zprIVUmrWjaS2LW1lOI337HZP2K2e45YTWlXEEAokPswIUSSYQlAiATKQksLILSEGUvIcT69pm5oYS9AxZYd3oIShsRUhwHrbYKuKeVyYx5kscvm7rK/JCRZXOkDr7gqljghdODAxGNp6hfMJma/R9ecZ8zXnZBgSBAzJtETTFOKgm+nWHfVPfhV+4ItM/9HfZPkP/za7ZsWni+HXPril23T4FHh7HvnmJw/cysjv+NEKWWlOtuOvvfxx/trb/wrb+TX/vb/+Z3jyX/oq9Z/8x/E3T4naoaOjMoZGVWXFnxU5VngBQij6xWOUJ9eFP5aEpJGKd69e0NoVr+4/4jz+CjpPWNOh9YoljIjcUNst8/Sm1ItioK4t+9MDt9fvIqVFZIEWDYQZH0eCd3RNZp48IQ5lYEuFUAWrcjoeSx4mXoy1uWzr9sd7rNGs2h3H4z3GGGJcWK07UlQs4USYE0oLxqW0Cxa3IITEh1IePR6PbNYa5+5RWhCyIyUwpkHbAtc/nt+gZc04lBxRjgKJ5njas9tu6ccz83ymrluMWZeEulqhq7qojdRMW0ecn7DaUNmGzeopj4fX5Axd1yEQBD/z5PrL3D98hm8cSte07TUxLjwe92i1oql2DOMJKXOZxcXSWOhawXb9DiGUlDxJoUQHqhAr/DQxLo+0zQs2qy1aKfpRsCwjShgej68wWpSt6NJDmmmqTSnzWkkKit32HeZlQApHW3fkXK7U5IQRFl11WNVglGUZMpv2in4c6Oqry6ypkE6VLMwKJWu0kczzVLC7yuKnmVWz4TzskTJgbYNSHSH8FsKT0zjR1BseD58Ww+eqtPpD7PFhoa4b9sd75mXh2ZP30bKhtjNWt8imQuSCrz2e7miaNT5NxYzgbUE0XBAndbVimnqycBhd4ZeBxXlCWLha7xDMzMuJLNNlkCZR0uK9Q6qEUoZlWS6fug1VXV2wm2UIrVWNNS05hEtB8AbnHKfzPbUupD1lFTFEYoBVvUJimL3g3D+CSEUFZDdYtcZnQG3p81PmcE2SliAlOS7gB8IycPKWt9MVZoms3UR1GmlbjfqD/wXi0yuaP/+f8Nt/7W/zTTHyc+kfJa1rPn+j+fEvWGo9EYJlDop+gW+PX2KOFidf8Gr7Q2xdJH/j28jgSc826ApEFgRp0dmiUwUsCFMRlKaPFSFmeq9ZV5aV1uysYSMU16sdta15+bBmnl8S0z3H8ROsbamqhmVaMKYkkaVKVLZFdrE430KmsVum6Vg2bfPqAm2LSOVIYSGLSEyl7T+MPU1boVWLkhuWKRLlQgg9MQWkqhHC0tQrjIVxKsx35z1KVwWiNt+jtL2spd+itUEKwbJMIBbG6Z7G3lDZBhcOWK3xUbFdb2ibjpxv2G3ew/tI8IFzf48SkvdefJHFzexWt4X4EDNaGzIwjTOr9TXWdCz+hJQaYxpqs8G7TEoBa2tS8gzD+XICr0p+r9syzwtZON7ufxXIpFzT2DWVWRdA4FSyRM+u30MqW05pecItc1kQKNjYa07DHV1XAR0pBa62T1jmkWm+v6Tma2r7lMPpUzarG6xZ0zYbggORDeSFdfuMggweqGyFoiGEiSwyKXnaZoOiYbO+ZhjOTNMjdd0yzXu6rmOc7hByR21vOQ+vyMQL76o88HJKIOB4fqTSXbG1qJJvkyhy8qy72+/9oTTPBT2w7kp+xLmENZb944HV6orT+YDIBikC43BENTD1DruWSAwPD99ke/Wc83QmS8M0HGgby7rdMUyew/GEEIFN9z5aSsbwhhQKhN3aFmtq7vcv8WEkhAlrK2JIXG2flRrCMrFa75iWE8N0uiiLe9p6wzIV/XfbdrjgSBFyiChVEsBZCLSoMNpevGARSHg/47W9wKnKAFogETmh5IbKbnA+0Yd36cUajyWlzDAPDMNACgvJBfq3B8YRuu6Gl8ORNJ7ZLZG2EuTPf4mX//WK+ed+lR/+2i9xfv2S+ff/Tp6++31AAjJSK7RIXLc1f8D+Kodv3PB8N/PuzZdxf/0vw8/8LBz2hC99gPu9P071+XeRX/oCjV1Ti5a2aksHr1tBu2LOARc08+x4FJK+rXnRtWy0orI1n3v2ee77Gw7HV5AOGDK7lSGkieP4KbbKJbErEtaumOaRTCziw7rCh8iTJ5/Hh4V+eEtlN1zt3ufcHzA6M04jmaW84VKkbp6hmsi0DKy6K+rK4FygrRucBMSC0UXhtFvf8rh/Q2Vrnl39MOfhEZ9ObNc3BUOcIsYIJOXXGAXkgFFrxuVISFOpjbgJozWH06esV+8hksA2ipgd1u5I3uEvUQOlNPNcdPTWGIbpAWMLO1yJiiKIdHTNlmW5aLTngFYldyalJuMZ55H1akdlWs79gdo0+OhQWjOMrwlpYbPessyRxc1ok/FuQeuazepZAYpedOHWGPrhDY3dsO42iCwwek3MZ1KMaGUYlk+4vrpBssXIp/Tjy4vlp6WtnzPM9/gwUOuC+e26mqzXZX6WC2N+3T0v10/3FolB6y2BiZAjS5iQoWIcX5WSvKmKEUgsBCdYdzcM0xlQhCiQolBpldBM8xGBIafv3n37rjOl//3//U/kq+0G7x2Ld2TAqjIMrKoVh8OeblXzeHikrksv7Tycebp+xnlwmGZBaMur+5c0puX59TMeT29pKoPzxf4xugGjN9xsrjkcXnN7s2NZPF3dsdtd89EnH3N/fsRqxe31NQLB9fYJIkm6Zo33iUN/V5rtKZemRYTD4URWiafXN9RSIlJCacPpNPD+5z6HjwtBpLJJHIsxtdg6EtrKoocqaGK0AB8WkJKcDWNY8ai+j2C3RDQuRCY3Mowz6u4t7te/hTAN6cWOz94eeHN/wDQJYTNNpdi2FSJE3u4f2BwHvvQzP4P/2m+QfvIH2P03f4r63adks8XJa+6PiXGW9AGWPLJerdCVRY0D6nwi/72fx3z7Q+zXv4GOEfOD30/17ntUX/0qT7/8JezmilDVpLYhVy3KWrStMEpy06y46RqurKUSoHJmiZkQAzWgU8LjePPwEZP7lCRKyTPFwHnYY6sKJSxde8Wy9EjZYK2iH/ZIlVG6wS1gdXnjz/5MiK6wd0RNzgEfJrp2g3PFACJFW+Y1/khKnpQE1qyI0bFqr8qVTQpC8ggUMSysVk9wS0/KI/PSFztz1EzLxLKcicxYY5ECtFqD8MQUWJZyxck5YlTJZjV1exEtlCKrNpb96cCmW6FUeYPVdUc/nFjcmbpaU1cti+tp6hXLUrC2Gb5j4bWmwgdATAhRkdJSHnaqo62vCNFzt/+4pMF1GTZbu0JyoVvIhXHeI+SCkop5HGiaK/QFnJiyZ3IlkxSTQ8mKrl3jFn8haE64MdI118zhkeBH1qsbfFjo2i3BlYLvEkYkkqa+IZNZQg85oIi4OCO1JYRw0UhNIARtvcPqHcfTW252t4DCx8LCiiGyWd0wzUequmKc+7Ldq674sS/9ke9tpvQPvv1NNt2aYZrKfVUrKq1om4bjYaBp24uETiOkKENDaq7rW17e/TpjOuLDgosOxMS3Pt2TKHK831y9ppRZtYk3bw+4FPn0oaiWnXOkUPg9KUa6puL+8R6EwNojdV2xuECMkmkaS7vaeZSUF51QwuiEG97wpFkRQ0DUFcvi+PTlG4SC0ziXOII0xaA6TsVDohRaQlUZFnfm2dOnPOwfSNnS1B2Dm5ibNc11RjerYleJApEXtuk1vn7L4/r7ePXhSz76xms27+2omo4lOK6ubvjie885Pp35y196yY3e8Ye+/adY/61f4Rf+xX+F8c/8P/H/xB9i//t/hKVu8VvFOL9hfnzLNJ15UAHTNGUlmxP6t3+V+Xf8MPLc0378it0vfQ37t/8O5s//JR6vd2x+7MdofvhH8F/+EtV771I/e46JDqcNLkT2y8SmrtjVNWtr2GrNSmrinPjrf8XwzV+p+a/+t7/Marfm8fQhWfbkNNB1V4Tsir8+LWQiSkVO59I7SzmT44xUBq1rUkg09ZZzf0BQYXRFieNGtLTYtmZZPFVjOPcHqrrGLZLartDaMo4nKnPDNL0iXgrZKQVSZenHBySCyq6LKDHmUi1ipLJrlpyRWhJcROmE0S1GGKo6Mk092+4ZIXhso5Fa0Q9H6qpB5uJRK8YVxeJmmuqafjiQUiFLDOMDUoVSWTmXa+h6dcMyT+TkEARcGFnCSEyOrn5W5BccSSQOp4GqbjA2ls1e1pA1yyIRDCyLR2tBTiNSGGqzJVtBjAFjAi6cyuk+TETdlFqTO5f5kW45HF/RNFcI7Rn8y/JvUR4fS8ev0Akm5nliSRdipcrU9oacPC6c6ewGrSwpS5SyaF3msk3TIGkweoW1j5zH12jZoGWFkQqhMv30gAs9/bIgVOLUf8Y6fffr23c9Kf2P/6X/VibBsjiSyIBk3dZ4v5CzQElzsbnmi9EUcpKQHaqqCTGVdrW039G5aGMIoawEpVTEBFqIC5CtEAlS8uWIX60JQUCONHVV+N+i8LC1Mt/JhCAo+iVVcLAhZJSI7KxinUuRN9cVQluquuHN3VvarqGxLfqCSzkPI0uI9MNMXdUIwBqD8zPWWkLMuJgQSuPEjk8Gzer6hufvvI+tW5Lw7OwDennDfm9ZHifOf//rnMQa/+yab3964Pp6w+/48e/jvadP+Le/8LP8xSe/ABn+qb/Q8N/4tVs+m44cf/lDxr/015h/7Mf57L/4+3E/9IOYuiXuH3jzy7/E/HhH1mBai8iR7foKW0E2giFlVEy0o0PvB7rHE9X5RPUrv8Y2ZNTNLd2P/ij29/4e5HvvID54n8pUKK1ZVQ21MjzfbPhc1/Hxz2v+R39AMA3wT/4P4H/xf074dOazh19nf/4a0JOTQKpiuRBC07Ub5mW49L3OJCJG71i3G6Z5IkSQovya5CPWNsQ0obTE+XChZwqQnnN/pK5aalu2fsP4htru0EYSU4HSQSaKRMoTWtSILEn4S4F6x3l8xIeJpquwqr48rASSCu8dkQXIaFmR4sQ0jdT1lkzkavuMcR6IwYMonPjFT+w2txxOLy+ZooBAY6yFLFBCE8IIIqJUebOOyxuO/ac09Rata4xaYYxiGA4IRPEchsL16pprtFoxLY8YWZUqlA84fyKLSF215FiCnELlS8gxQRY4f0TIDmuLuNN7z3bznNP5AWM0WmsWP2JNhVtGNqsXTHMhACiRcG4gEamsZnFnBDUpKaSUXG3e4XB8gzIVIYI1FpAYo8qG21aF+b04YlxIOVDbDfNyuvyahYwnRkdOI5Wu+F1f/ee/t5PSza5QCBHgfSxRfyMZh0RVlcJrPxU0bvSJ613H4TShqxXz5EkiYaVg1TX0/ZmuaRBCcRgCISa6uoYsOI6FCBh9JKWEVLaA1PyEUZamNqxXLc5llsWzabdEn7FVSwwJLQWJjNKS50+esQyOSgqMG2hISKMQbYNuanbbHW0jiS4glGH2E9YKntobsjSc+4F3n97StTU+LAzTgNaatt5x//iWh+ORX/7wJR8/ZD5fr/jmJx+z3qz5/LstzSZyf3eDfgJPbgKn7Q+yPhv23/iMD1rLl3/oi3zxneesmprf7X6Q/yz8BnWWfP+vTXzrp/8C/ccviXVN2nTUf/fn+ML/5+f5xf/JH+fv/LE/xrOv9ajjx6yridPDa8RSY6ua0+FDfvhHPqBeWc5z5NWbM0275is/8IO8ev2SVw93nD5Y87u+9MMcvv5Nxm9+A/2//RlUEqh33kX9rp9EfeWLtJ9/n7BZMT59xqHb8vr1DdFtAFt6TxTh6PtPfpTgZ3z6jBjDJYnck4Ngf9zTti1CCqzcFXKnhHEe8T5ytX3Bw+NrMoGmWYEynPsHBJHr7TuMw0jTtiyhL5keXXhOElWY0PGENO0FIatBlAfB4iZsXaNQpGzRVWGBG22xtrjgyvxVEkMi5oXN+pb96RXaaFLwZCJGa2rbMrkz5+GRxY8oJYhhLP66PHE4lzehn8rVzTnPqr3ieHoAFWnra4b5DU29Ldyk3LDpPkdMgegFbbUjRUdOhuvrF4zzIz56rK5ZFmg2K87nPaou/kGpNK25wi0TRq3JQuLjwLIs1LZByLqEOWVNTLkwp1TLetcRAjy5eZ+H42cY6emajpQSRncsbqJtbwl+Joae9arEe1KK5GSpqooYM+N4JCZPVVcgi4G4GEpmEBdm2jzggy/qreGAUgYpNDat6ZodIZX8XaVaJndP5rvjcL/rSelf+Xf/RJYXO2u/FKhUV1skgcooYor4JXO1e8apf0CpSN3UDONAq3d86fNf5nB6YAkDOQusthij2Z/OOB9Z1TXzNPHZ3RvO40LbrOnHgdVqy7E/seoqbnYNOXvG0bFZ3+J85HQaubq6JiyZlCVkRQyB7XZFWBaMstRSk8cjJnuqrsYJkLZsjA77e66vn+OdZZh62lWNkJI390c2mx23Vxu0AYi0rUGqzP7wyG69w3nP/b7nb/3qax59y8uHEVUpvvrbvszzF9fsNh1Prh8ZZ3h83HLz8Bb90RvkF36C1bsvaJoaqQo9YGz3bFl4V3acHz/j/tOvc/rFX+L4y58w/8Zb7r/9lv/bn/v3+Pj3/G7W45l/9q/863xBnTn19zy9fcpqveZ8GlivLClFNpsr7u/PCDRX29uSmCfwrW9/SLe7ZZgD26pmPD2STgN86zPU1+54/KWPmE4T4svv8eInvsI7z/678G//I/zC119z/u8r/sn/2cjVTSRHibWGff8hUhYjyal/VSgSF+tpTIFpGks9RwiymBG5wN1AMM4Hprm/6JUqDqdPqKsKkaFtN2hVEWK4DE8lVtfM04ipWvbH16y6DW11xePhQxJlwDyFz1jXL7BqS1WtGacjZLjaPmeYjlhjEcKwhIVCwQt4H/ChDMa1KDk1KQVtt2V2C8N0R0bQtRvGqSimrDWMY0/T1PgwFXaUNkVCERPDuC+hUpWIXpOFL9fHxdFPe7aba7RqmecjSinW3S3zPBY8Sra09RMQJZyKyIhsULTEPHEeHtit30HLjpDfQLL4uGBMuYU4P5KiYNV2pFjj08S0HFCqQhnBMhfkjBFrfPSENBJjorJbUlpIeUYKjdYNAr7DnI9xpqpqlnmEVLPdvMdxeE1ME1prtNCFt6Q1p/NbVu0tggofHFYrtLRIXTO5AykmrLXkZPjRL/7hf+hJ6bs+lP7q3/mXMyiWxbMfD3jvef7kXWY3cji+ZbvZ4F0kJ9hud2XuZBKVtmy7dzCyRqjM/vSaurYINMEv1HULUn0ngj6MRxAFzO+8w9qGYT6DCMR8plIGY66Kznka8a4QqRe/cL8XuMmybg3vvLhmvy9/1mF/xiqLxqM0SGHJSdGPnhBdwVR4Q4wgBZz6M6builhRC6ZpwliNlLDqGiorqY3l1J9Zr1pe74/8pz//DT57deC9z72DXHWkquX7fuAF77/X0bsNtyvNk+UM/iljdUvIASMVWiU6JXi2qcj+Ea08y3Jinl8zL2fW7Y5Ve8Xdp6/4537sH+fvbt7nRRj5s9/+y9yGPSTJ1WbH5AasaUkhMLuRqqrIiWK6cAktFQBZRlIOaFmTU0YZxeIWvF8wuqJLK06fPPDJf/izPP7Kp7z3s/9H1vNPQhOo/63/APljb1DKEENivdpwGl5TtFPXhFTCsUU2GUt0QGqWxdF1K9ziaZstMYILe6ytLjkzcyl+lod/P5RhaIqRlCN1tblcL8pWKjIRfWDTvUNGsvi3rJrnJErvTWaNliuM2bH4E973bFZbcsxY2yEwjMuAUsWwa6sGiaY2LS6MxFCQsUprpKo5DZ+weMd2/RxQpOTRCryfWPwRKS1X2/dwy4xSFuccIc4kenL2kOui9dItMUKIE1Koi4hCXUCJkLJBimJqXq9uOA8PtE3NPJ8hw2Z1Sz+eiQmM3tE1Lcf+FSGXeahVmq55ViQISaFNpp9ducbGPaQ1Rlvq2qKkoNYbTv2BJMfyeI6xuBbJl2BsgzF1eXBqyTDtISVqveV6/X0I0fHq8ZdpV7I433Jmdie06fB+REpzEV1UiCwxWiFUYpjOVLYjJYkSDT/8wR/63q5vm7UlBEnbtmw2G5qqYVrOrJod3p242T4hxcRmfUtTrZnmHiEE4/SADzOr3ZaUBNv1M5w7sl2/x7QcSDlQmQ5rao79wHq3RmARQqFlmePUtbxICtdIqRmGMyl7NptS+lVUjLNGSwgOurpCyYg2kWk5MfmZ4/nE9bal0ZaHY3G2JxlJBHp3hzEdj6eepm05jHvEXNAX50PP0DuE0oQQ8T6w6dbUVYUxlnG5Z5pnGiV5tqkYHt4ipxVTjPzN3/hF3v/CO7z7/i3b73/Bp36F8zD2b4jLwFYvnI933K403OyoKk1dlfqCC4G22xSovjuirxX/wv4X+I+XB756+ogn+UzKZYYzTEdiFhid0bomzwspQkzuMgRtqGxNToIQHT4sSN0SvSenRG062rp0kISsWP/Ac37kK3+Uh/1HxH9ZwU8H9Bd6qi960PUlM9NyPN0xuT1dc4M2hjgFlNIYabC6DIbrZoe1Zf1/ffUu4/jItAykPJGzo223BFdqE01dqgtaWepqRwgzj/uXSGFQqiqdNGY27Q5BW2SJqVyTpAA3e6yukKKiq54V/LFpETLST/fF3Jsl69UK4RaaqiOGmXkaS5LfCcZ5IIQzT28+V76ubrqkszMpOJS0SJFZ3HTZtE2s2idMY1+yTEkCgidXX+Lx8VNSXtisrxndCWtaTue3eHdGy4a22uHDSEqgbEuIM+t2hQqRh4dv0bYr+vMjxpQt3+TuCdnRtc9RyrI/vUVIUMKirS79P605HB/pujXnfiTJQgvIMfLi9j2O5wMIzTCcaK6u6LpbQpyZpz277nnZkvqBxe8RsnjahNBIWegebl643n4/Rt7i04SSLSpnKtNwHk6EKEh5wKjyoZdyKAKGOHOBXSAlTPORVXuNUr+FSMDf+Pn/U7aVoalWaKERsi7kQFVOHmTFqtuRoibGTEwLVd1yHj7F+YsPLmtImaa2GNVx9/iaummo6xUhjAzjXdkcxAySyze5qHD8Am27xbuFqqqY5gGlDd/+8Ou8ePoBw3TiOB5YZkdrO5Qx9MOBnCXOS6xas91sePnmU14/PuBCoq4MXVOzTCM+J94eDiAzYUmM/YKyFbWpUELhQyYlWG9qvvD5d5FZ8smnbxknh3OR/fHEti3+q9f3j1xvGr7ylfe4O93RbBo8nmfb93mye5+HfmJj4elGMruFEEZu1jVXV09LkK1qqCqFrSzRz1jTMs0DMUHbbBjnI8ZoRNbkGMmUQGGMC1p2VHaD1hLnxqJrSmC0RknF4jwxOZCayrZM8yMhzMQ0U9v1pcSZqO0WFwJ5hvQrT7Hf3xO3pXkevIeU8Lms1xfnS1o7Z4ysUMrgwgB4UpJMrqfWO55cf4m7x28QmS788DI3tFqTkqC2VyAyVltiVgzDkdnt8WGga68IMRFiT203NNU1yzKVT/SLEDJ6z83Ve4QQsfqKfjwgjGMY9+Q8o5WhssV7r5TBub649WKkMU9RdKB7puWRpu548+YzEIG6WRfcrtRkIZDaIkR5r4zTI9asERm221v2x3sg09gN43igaTrW3ZaUJQLL4fQJVS3xYUFry+n8QFfviEKSssNIBShcGMmXQbLWHUo2+HCgH/cYs76crIp6fp6KlMP7MnCvrUEIU+pWqkJwicekCqk1WlmCc9/huJfysaC2O3zqacwG50d8nPDR0dS7srySgnE4F0u26mjs5rJk8DR1TSJw7o8g0wVvXZEJhFxuJMt8ZtXtWNxAiA5rGgSK3/6V/+H3dn37B9/66TzPPbXZoaRmP3yEkIbK1sgoMHaDVB2zu8eHhcpaAJw/o1SByAspihVCNRf63MjsypE3pYmuXuP8SI4CbQvnN6WEjw5jKoxuWTUbljkRM3jnGKZH2qbhsN8TVWTdXmOEZX9+y7Scub16l3GaMVoTwkI/jzRVRwiBmD3zeKaqKz57uwdteXx8wztP38FPkSUGiJFN84RuZRndCRdP3OzW1NZw93giRkVG8Bvf/pivfOkDrExMfuFqt0OLQKRn010ToqBrtvilx9gVq7ajsi3zvCBUSdCGHNBaI6REXMy0je2IMRGTQ4iMsW3Bc6SAEr/JeU4oXbI1ldmilOFwfE1lzeUIrfBhQYhIpiBohNI09YZpOdG2LTE6jGwwujTZK9uQsyT4hapZM83jpYPm0dKUT0E5X7I+FJ2RKkHTxfWlsCsEle2QQmFkB1kQ0pmUAy4s5JTJZJQwWGuYBkfOnvXmCq13pCiIaWFyjygpQRRP2KrdlGuSX/BhLOZWU+NcX6IEdUfXPGUY7zD2wo0nknJCSVFO39UVORaMxjSPGC0IocRPYnbYquB5K7MiyzLIFUmTMghRCtvGNMzLntp0JaWsFPvTa5Ss2Kw3uGUu/b5Q/mv1ugzdjcaHsfCqdE2MESErpmWgrcv2bnIz625LcBEXPcZIoh/KxlBapNKFwSQ1dVViLksYsUqXQDcCW8sLcjeSYsCYjnGZ6GxXrq7LQsyOmBa6pvCz+vkVjS1YEmTE+TIWUErh40KlmuJqkxKFxuhcpLHdprxeUgJRXbbsMzl7hrFHmUiMAVttiW5CiETKGaUkP/H9f/x7u77lLItlU2iEsaUyEBLWNIxhwGRBWxmm5YQQnsXJy7FP4paFtt0hKEaUYDyCMjSr6Nit3+Ph8C1OFzGfkpYUApWumJaRypZNHSROw5G6WqNTR73aoY0i5ZnNVZljNUbRVBvm+ciq7aibDdqW9ayQifeunhJjIATJdv3FosqRklW7oa5XxPh5umbLk917vL77CCHhav0Biz/h0oHD6Q11bTC6ZrO+IobEk9sv8GM/+ONIOZUXjtBo3ZJFuWMbbbCmK4PY+Uhd7cr9ezmjjaJutyzLjJ8fy+aQjFaaIA0xJVbNmkjgNNwR5nL1NKbB6oZ+eLyoihwpZw79G0AhZcYlT/QzRtekFKmqCkGiqXfstiXRu9ZrjGoRBlDlZLosPVoamvaaKDLH81ukEHjnkAJk1ZFEJgTHuf+MzfoWayqmucwm6rqA4pQyzEvEqI4gPCCQOaMuJ43tesfiR7TacDh9wnp9jaBcKUmZEBKzO5GyK2wr02B0wHlPmE9oXZeTgjszzT111SK1xPvAMbxGqZlzH6iqFUJmgvOXMKRCa+hnj7YtKXtchExijiNVvSalsoCw1RV+nnBxwmiKwYTyAGuqlm1XTvkpjxyORxY/UxuIwaOUoZ8eKQqjiiXMECJS1WhZk0Ri1V6XAnMq3kPvBdvVByzuY1IuenKrDVop5nksAd8QMUJdTqaZHDyLLz0zZCnY1tU1IRwQQhQ0jK6IYUELSYiOlBTr7jlvHj9i8TNGBka3R6oKoQ2d7ZimcqCoTVVO38aQUgH1DUNfkmVWFyOJyIzTkba7xvuiOG/qjuE8UFcNTdMwjAdkFuh6S84T4zxdiBv/8B/f9WfHaX9BJQwc958hdWkje99gTY0UoHRm3W1xbkTIjBCqONRIxBBp6gZjDDknKrsi+hJsnKYjShqkKElbIQQ5BbRuMMnQ1BuklCx+JAvLNJ0I4URTbwlxJOalIE0vxUtlFFJZjG1QtKzXL3h9/xs0Tclo+DCCFBdpgaQ2K1IVUdJi2w3j2HMe93h6+v4BFx220mgl2W2vSTmQUrGWeunoh3vmeeHmesOSDEJqpLJIpZjmEykH+uG+zFt0w/H0hhQ9zk3cXn9A3w+EPCNERfCOrBIxlEFhSJnJF5RpJH8nv5OFJKRIzInFLyzLQNtt8MFR1zXOD8TLm7BpOpyLLH4ihnLiOo93F205iEuNxi2/2SSvWIJn3N+htWZeBrTM7DbvMc8zSzijjbgMqQVaWc7zUMw0MeF9KB8cqr5YjwsL2od02c5VCGkLziZZAg6tCpS+0B8tPj4USw6OploDBr8UppVUBR2yuGOhK5r2ciovJ6dl8Ww3TxmnpcAG3UxKnq7bsFzmYcucaJsdMQj6oWh/YoxIKQnOo6Vl0z5jnHrWzYbj3SNqXQgMSje0bcXh9FnxEKqG/vSIkBGtFFXVMk3ltGnVCqM7QvTkfEIKOA97YnLkpJjdwGZ9Sz/cIWTpir15/EW6ri6qcauI0TOMZ+pqy+wKYUEIeaEPDLTtlvNQsDtaN2jRkbJjXjLrVcvpPCDEyG79HKMr+uFIzAs+FQxRXXe4eCJLQWM3Za3vF6RoqKst535PT09T3xTK6mHP/vHEbrdls9mQYmaeHW29IwdY3CPTPLLubqiqQkqY3UgikEJCZYEQmqbumBf3XR9K8rv95KotTJ1hfovSgba6odJ1WRPaDq0qHvavydEjKaekyja0bUvXrkhpKPd6YVFC4F2irXcFJh4mVs2WdXuLkg2VbVitdoSQiClcsKQj0UeUsMToiYy4cOA8XJxWqlArQ0q46KgaS2YhxjMiJ66udtT1GufnkhxvtszzA0hPv5xZwoJUGSkSkRmfe1ya0cYiZGIYRkCSosaaDmMszs/04wP70zdJ4oFpPiKVJFOuY4fjHYmIc5m6foJSdREWKmi7NcoYJncmpOVS3xmBTPQF8yopCuvTcCyueGNp2015uKSZ8/BQ6jBCIJXB6I5Vd025hQs2q2dY09EPj8zujABiFGQkMUdi8ihZ6JBCFh4QotQtbFUxLyfG6ch2fUPXXjONM4fzscxHskKKgkD1LmB1S1NdFQtHmFDK0th3sOoFUmrc7BjPQ0HCjCcgcx56xnkgpZLZcc5hanvhCglSXC6bqYUUFhpbSA0hpHJy0itSzJeAoCuSzPJPQKuqgOOEvCShK2JMlwRyBgQxgL5woWL0TNOA1SXOkJK/ID1GTuNbtMkIJRnGnuOxJOqzWJjdCdSMsbp8qNmKae4Z5pEkBCEH+vERxIQS4L2nqjpSzuVkjuc8HhBSFH64NAiZSdFhdUOl1wTvSLm8JvIl9pKTuDysJcN4xKqaxm457N+QkqMf32CNZllGqmpFCBIfIsfTA4sbOZ/vSSkS81S2btKiaIgusCwjh+MjPpxY5gCpRquOyZ3JaEIWPHn2lG6zJgtD1WyIWeJDKLMun0BMvLr7GudxTz+eeTy+xvkJIX1xP6oG7zNGdd/7SSmLhJKSxnaXzkqL4Ib96c2FhAfWCNxS0twyKXz2LGGmaQ1IUYbYOXAeDrT1jmWeiNmTEgyTQEpRBtPOMYwj1jaQi0gyhNK+XtwZYwwyGSpjoN1Q1TUxejbdDeN8ojIV0xgRObPaduxPH5etVgyAoK7XkDTXmxfMfkRrizeWlB2nofxbtKrZdreM8wmhwFiFdx4pDc75Qqw0NWb7nJTC5UhcKrTWNChdipslbd7SNVcMQ0CpgE+ZGDyr7oZMwtqOOrU87F9TaUvVdDg3U5stix8RqrwIUxBkJTHaknPAVgX30TVbnAykCJVZIYWish2CYokVYkJKhRCKtqkI4TKIRBaKg1QssSdnqGxLDBFhBDkv1HZbGDhCogysV1uUUmQxUlWlRjCOE09vvsLx/JYUJyTFS7b4PUIolDJUbYX3Rz57/RFXV9dY0bLZ7Hh4uKeyiSQV2mjGaaRrdyWbIzJNc8X9w8coWSGFpRKW2nZYUzFPZ2pbumdKq8uVS5BzYHF7fIiM88h2s2OaR6zWIBQ+eLpmxeImHg8PRXedPbM/o01NTgplFefpjqbe8HD/BmMNUk8kMZFyIKLwcSLmkdT3aNmipWVxZ2xViunL8pbH42sQgmvzhNP5oXwIqEhMM6fhdZEyBgsJqqrFOYfIEqk6hqVnnt8iRKDSa6xqiXEsH6xR0FQdQhq0VKQA59NI1xSwYgqQW0PIkUwosz4fWJYBazRKNuwPR1btFkiM00hjbqltg1Zr5nDg0L+hrTIia4xInM/3eO8YprdksUXq3aVTJ5mXkVlE+vMeQaKqO0IEYTLQF5a5eYbRhmWZi33a1qza6nt/KKUMKQsQmro23D9+QmUbuuaKce5Zr67pmmsOhzdYY6htR0qZkBPexzKsDY6u2VFXhe3Tdjse9i/LFgGPiAoI5OQLTlNquq7BO4f3GSXlRTgomOaFnKCpGuZxRkiJMpquXrMshYYYc+I8PKK1QmCobY1JTclFLR6ipmuumKeBzfqaU/9IVQm0roGMkoq66kghU9c1ITiELAM7rWuEhGUZMGaFNal0psyGpl4xzmdSkmXjCAU6ryt8yCx+oKkq+uERIcH7cgq72jxDS1k2l8bg4x6tBVBhTIdbEvM8IWS5ZuRcBAaNfcq6WzMu5/IpmxNKaLxfsLZE+6UoMYvZ9eVhD3TNVSmypsQ8JTarZ+QsOc8vOQ9vyQQWr2mlwufA/nzkavcc5xYQCSnK8LOc3k4F7FbXNE1p7Du3oHRmnmZ03aJt5unTZ6VSFCIhOzbtFW29RuiIP0+gJMlLhNYINYIEZSpSzEjj8dHjXCSTEbL00GxVU9kVzi9obei6DWM/0XXXkCXBD3g/kGyD1Jl+PHHs31LXFlsZYi45G2P6UnWRNaf+RGUblIbtboeSLTE5mkrjQo+QCSEqNqsrpnEgkVBKlpOxz8xuKp41u6JrrhEi0XZPkcIQ3UJXb1ncQNNuC5o2ZFIsI4qmbkgxM00Tzi9Ys+bYjwy6RDyUomSfhMbNkZwGanNTajlJME0zu9U7WNMxnt8QkyMEd/EiOoapzP5kTtRmzeRGjuczkx0uC44yKJ+nBS0XlITzuIBQZTGh6pK3CgKZMj6OTNNM0zQY3QGZnA1t3eF9AFXYWFqqizyzxDlMtUbK8L0/lPp+KF/0lFiyJ8QEzpdZkDR473l0d7jgUVZzGk7EmNHGElwg54xAIWWNDweEhf3xddnEeEetS3o35RklFZmGb330LaQUbLuudOmEuGRTPMsy09RrLLpEBmJkf35EiMyynNFaoXTFMs/UtiURqW3BX8SL5XPV3OJjj4+OeSphOlDUdTmCSymQSGKK5XSSyrFeUONDOfIbs0EKe0GqJM5+Tz8+MC2FaFiZLfvjA1JYbq6fXu7pCvKCtRqpyhUtxUxdJVxc0LoQPI3SJEBrxTDdsyyOyq4h5PLCTRqtBHW14u3dh5hKkYUnxshq+wyixMqWIMu8bxyHS6p4wImF9WqHIDBMM8a0F6h7BUiqeoVfHNauUbohutL18m4qV0tRI4wkS0+IGcGCkobZ70m59BW1biAppILFH7BVuLCPBKYwRUhpJs2hoC6RGNHSVBtcmkjZcj6fygZPChbvSGEm5kB/esQowbJITFUxLmVeo4TCu0jTrIFM16xxThdOUIacI13bMftA8A5NV7ZP6w0pCeb5EVu1VGbN4hameSE4T11DStBUK6ZpZFnKaT8FQVs/YX98iYt3hDDR1CuskfhgaMy6RB6yoG0143RG1xKlDO1FSjDPR242n8fqLTF/AylgWWZCDExjBKtQesfx9AZjUlkm2BXLkjmfPSkM6O0O7x11vaIxTzByzelwBFkVvEX2jP2Zum5wvi9EBrtjf3iLsdfo3EEMDMOAixNtvaY2K5RoCigwFylo8B6jS/xgzh4vYF4KV2oZJVJ25TmRwTuBVjUkj/czbQMxJIRK3Fw/Z5gWgv8tPJSM1Whlivs9RypT7rPlju4QKpFDkQPM83gh2Rm0KVhWa25JIXD/+IqQJ5yH2mqENHSXiL3UUNttMZhEx2a9IRNYrVfkCNNyZnED280ta70jZUHfDwiZ0NpirWVxIyEUM22rL7MRN1HlyBI0OUtyCgQ/c4qfULdrEIIkIgqBUpq+P+Nj0VbHBFIZYiwZEKUzp/6+SA3Njnks5MOQfYngLz2IzHq9AyzWdlxvBSn5CxVxzTw7XCicqJw1jV0Rk0cITduU8qI1DS7Ml95Xi8Cga4FSlhgi1mzLMBLP3cM3ySLgg8ZWGh8WzsOBq9U7lwpCpB/vUUpdThcUJnqG1haiopIwjAdiarCVZhh7dtvPUZuWeR5QqqHrrjgcX5NV6SEubkRdpI7OzSWnhgaZi7o7+7JaJrKEcxE4SFvMNUKSJRgjGId9CaoOZ662zziPj5gaxCU9bYy6SEpbxjBxnu6BluvdF4gxcDw+ErOjbixCdOSciSEwxwHvp0trQJSVuWyYpgOQqGyHMRVEyTgeaeoWq68R/ObrZMa5iVW7ox8fCoObGq0qXBjoh33Bd9jhAiWsqUxN1+wu15QRhCAjik9QtChR09QN83IEAvMyFCaVOxNSZN3dMgw9GXBT4vnt97FbvwAkb+4N+9NLUg7cbm64uX7Kqlvx+u2v0TZP2D1/UnjfSpNjYtM9RWi437/kcBh5/72vApJ++AesqjVfeO+r5Kz49LOPAcF773w/5Mg3PvoHGFnz7On30VQt3gdsVbO4ASUl/XDkzeOHvP/iKzjv+Oz111m1O653L7BVTfChnNpyGckchzeM7g3H857gPVprktBoaQn/f3hK3/WhJHLH6fwJdVOjqJCybNZiSGi1oR8+pmvWyJxobUsKkc16jY8O5wNkRduuqaoOF86ch7fU1faSJNZE71j8Qm3agjmd99zsyqdd9KW019qubDdMW7pXUrKq20IakBbvJwwrNtfPLp70iFUrpOmJaebt2xO73VO2qxuk0qQ0c+7vS0HTZ+Zp5Gr3lMPxgcP5jic3N1jVYWuNjwM5gQ+Rpmqwdo1Es15vcf7Myra4ZWHVXBFjQMhEyJ7ZnVCyrE1zXpiXBKLEK1KSl9NZ8bGRy9cpREdOC0Pf0zYbkk7ILC/UA1/K4DmWhy8Tsx9RWtCYK2KM7DbPCXFhckfGsafrNjT1BqXzhdZZdNh9f8f22RV1tbrwrUOxBHuPFLqQJkU5Xc7LkXP/SFUbnBtQtcBYCblQAKyx9GNASCBp3BJRerkQIzJGb+j7e3Y3T5gnh9VdqXQkz6a9xseFbtVdPnhmkF254rcrhuFEFmVeVtltOX2HRAweHwuSxOiKmM+InGmrjq5d8er1QLPelj9fGeZlT8wLxjaAQCgYlz1CFBlCue4W9nRKDmNNGTSHBYTAOYfzPSEN1E1bKi3iovfOkpur93HLjJElOY+whOCJFzhcSomcFCmC9yCEhFwRvMSlmd26YRh7pmXGu4yg5snVe1R2xeJ63n3+BU7nR2Ic6do1TdWyNAtNdc07zz9ASMnrtx/zeHgoLKl2i/Mzzi9c757R1B2g8Uti222RCmY3M7kz281tyQb6ESEEN1fvs+pWLG7k/vCKeZmI0VOZin44I7VAKo0RAmvWvPPiCwghOBwfuHt4S4yBypboR4yBui2d0qprUEpzPN8VGuVv5aRktUS0OzKBaZwxxqC1QssNbX1FP7+BLMsnIZK26einPTH60n1RkWU+E+KEkqXpXdlrUvRImairjtk7FtfjfM961THPRzbrLVNMpBBYd08RU0WOkWXZX5LHG7QuLf6UPEobEAtaa6Ss0KpCKcESJNe3K2LwTMuecepLg93Yck2TNevuCcEvvPPkA9bdBu8HurYYPbu6bAuk1Chj6YdjaT2H8glehIiwuBM+OHa7F9hk8HEkI2iaFYs7QAal6uJy06W0qkSDqSzBOxb/QM4LMWWurq4vcf14ifxDW23KCSIuVLbicL6nqlcYbRmGC3FTTsVIKgtIfhjK10r6EqKMOSBIdG2HyBrvBmAuszcR0dpANtR1B0iG+Z6mWbPprjgPL7FakpMj5kxd7ajrHeN4JMSR4CY2qyeFkZUEQmqsMXifWDUvUGKFlEPZGkpKX0wIZjdgbPk+dt0G7xfIoGWLkg3D/Ig1Z0gQUpEezfMjLs4otWbqB9pGo4wp/O/zgWE+sUprFjczzY8Y7ZEikXMCFPMcEUISwlJEixQkSPCpMMGCY0kziIySBkzDNPWklBFSoURNV23xsSeEgACqypYTwJwQMpMBdRk7+EvX89Tvy1wtgqRGSwNa8di/xc09Vq9ZdTe4UWBNEbJqo8kJ1ustx1PRhy1u4HB8TdtusBcNfd+fSuVnzKXXlgJ1s6KuNqScL5EQRVPvIJsiCCCx6nYoYeinM9M00DWl4jSMM/N8KgsXAfv+BDnxpec/SluvuLt/yc3ueRGC5ECKicpIzm5hcYmmbVEiFvRPiMUmZBo29QZja17dff17fyg5f38Z7hr0qitwcxGKE2r8mN3qqsgcRaLv7xBKECO0zVNyLA8pt0xAScva6llBJcSlkGalpOvWVLZjGMqbT2bJNJermNSS2Y3YypBiZrW+LS73GAlhoatbUtKEVBAaKVZo2eD9SF13ZBRKC7JOpFRUTSEWKNm0lAFmjo55OXF7/ZSYZkTXEUOpUGg2CO0LoMunMptKqeR0RINQkn45lICishcb7xkpReEH+UAmkXLEmKYgG4RAIAHJPC1YY8kxINHsNk8Yp5EUHdN85ubqnQLJW46l/CgNSkFGYnVzCRhKtutrhulEFoFljlitsaIDVf6uN7sXjNOJYfLk7JnmVzTNbalxpInFnRDUdO2aeT5idJmXCRFJ2hTIGApjGkKISMDPC1ebz9OP94zpAR8C2/UNWQiG+UyMkfV6jfdLwXO4QMwji5vp2hYfHFVVFZIkiRBGTsMD29UzlIhooXi6+z4O40tgJqYFozVCGNrmCd7DemNYlhNh7mmVwAXHqtsRY3kIdXU5GShhkFIzTxN1a0lJIaqizfJ+xC1lrmaMxV+uz0pZ5mVgThGlLSpv0CZSmQqjymB4Dg8M8yMKybp9ivcRlAOR6FY3LH5kf36L846mXuODx1YNYVnwIVBZyTDObLpr/OQZw8iqvr2YYgRv715ye/OUF0/f/476KaXI4hzPn3xwwbEonty8R1U3hCcJctHQn/o7dptblLQ89J9Q1xVPn3wOIzWfvfoaKfRsuw2Nrfj4dEdlW07nE1dXazbrW1arDcsSuH94zau7D7HW0LVbfAyc+wPez0X0sN7y5OZz3Fy9y7Qc+fTlt9mfXtI1FUo2GFUeMUJkhEl4f2K73n7vDyV16Vptmhcch3tinstVoXsClG/8tJxBJMblRNOsWK+KHthHTz/0tHVDzDWnfigEwrigpUBIdQGrX5UvrjREDLNLKC2xVYV3AdCkJHEhMkwjRisyHoHEj5Fp7LG2KHm01ixzUbiM80DbdUyTozIWa+oL/lrhwwC5xAV88kglOJ73GFvRD4fCt06JwR1LpEDA4+NruuaKtu4uUDMY5oX1+inLPF78eA+keFFFX1LE1tTIHC8p1kxOssQHhCSFgMw1MRWjxjCUrpYxK3Iu+Zi6ri+qqaasYNOMVjVN1SLzNbPc430RMjzuT8Xb5h1mtWF2Aa1k+SSzq0ue5kRII+N8JCVNVRlAY0zFaXgEJDGnMncRgXO/p65r5nnEhKLJLlAyjzsEVu0tTi1kElkKnA809YqUcrmWhlRmaVWHyYbN+obgYX/4lPW6obEdx9M9QogC5NeaeT4jZCIlW2Y7w56uvWyIkkJrwzKf0ZXGNlv66VTmFqqYRc7DARcSRgoMlqQUiwsIJYlBXCoVDudHhFBUdccwLGQW5rnUOJp6Q1OV73VKDqkW5mnA6i1v9y9pmi1KVXTNBr/MjHNPyBMqCZrqmuP5hI9HVm2F5oL7qSuc94ikeHb9Ad73rN+5xS2B/XyPj8tFiJqJ0fN4+JTd7hqja9559gFCFIv0soxoLS+C2Il+eOTQuxL1wJDJ5BhZd1tiyhwPb6l0hcgC70txu646hAzMy4lhOOKj47O3v8LDqeVm+y7b7YZVt2XV7RBKcti/pa5aZj8XcJyWfPbyE3a7ha69oWs3dK3kS180fP1bI0p5hvEBY7oyn02pEDGFoqrq7/2hJHIpWZ76gtQcpgcQidNwxzj3ZZuSczHGNltSCjg/lgCYLfmRcelxbkEqVRr2fiIlwabdoaTDuwVkIdOd+0AiUZkLYkPpS8l0JhPLlUspfJghCdqmI+VIjPECMKckiXW5wvXDsZABjebYHzDaIKQkC4mtLsNLNxKSx8eZfo4ICTFDIjFOJ4SEynZYqxHSE8KMT4KQF0bXMy4ZrQU6Fdqe0Rv68VCSvaYhpYgxBucHum7NssxF4WM7tGw4D69ZrbZMS0BpzeH8hrqqWa02TGPJQUmpL4SGA1JJ6rpkghAlsDr7kdPxHi0NrV2jVMPg9oQ4ovQWpTXee47DHheKC89IyTQdga50v5JjnE4Y0yCFRgpJjB63OKxpWfxS5liypmk6QJHEwBIsWc4XQkTC6KbMxdpd8fBJS4oRVCB6CbKiMoZudYMg4X2pI9X1CqkbhJT41LNZ3TAv/UVe0aClpaoKPdIHR9N05CxLmlkt5TVQKeZ5KYzqRpHjQgy5pMGR2KphHAYqmwBLXVX4MJQVfFVeCylnRM6IFCEa2rpmmhOVsQigH3uqanMxxb7i6fX76DwR8ogbRtrmiq65YXIzRlXsViuEUDg3MkyPbFa3GLmBVAKWVW2Z56nEQFLD9dUTQpp5ONwxzQP3D2949vRdjDGktLAsE11TGhVKau5Pb1mWhePwgDGG4CfquuZq+w7WVgzjQI6Jm9tnkBMpl9/j+dMPihNxPrAsC+vNNeN0xLmeYTiwOtzypS/8KCInunpN6EqB93h8JMvMOHmudpZPX3+DpnnN1fYZ7z7/HOSG2u7IYiDlGR97Nt1zlFwxTp8S5Yxwv4WayTL2oDJBOfbHD1GqmAtGPwACrSpSDMSYC05BSUKYLsqbubC4hSkDryyQOVJV5sJVCljT4kMPCcZpYN21CDI5eZSyjON4aXWDVgqpdJlZUP7f+1Lyk7qA3rUWF4BYwzidyHnBB0+ix/mLb17KcpT0Bmv9pb7i0NYU9otUDMt9ccAbQUyJmMcy5NOZkCKV7VBJFtSvLYldVCxuO1mqNSHEck2cRnb2SfmEDJkQFpwfqawiREVtntFWT+nHD1E2YqzGpZHzkAvQbjpitKZraublTEXHODti40kexumAtorVqsPo+oIeLYlogJAmTsNrVu11gf6TeXh8ZN2Wdr7RAJaYHJvVxfwrYJp7tK7Zrd9hdgNX2/dRquL13TdJnMuJUdlL6VfS1C0xSrq6o9l2pKQ49w/UjSL6gK4lk19I1YRzhxLGTJrEjBIarS0mFMKlNg3j6Fh11+XamwMxRsZxvGiPJON8pqk7Jn8mJk/TdMUrKDKkRIogRU3AsSyetvtNHK6knx9YNVeEIAgp0FYbYpTlipkW1qsV89xjpWeeUwlw2lu8f4vW4SLL9Gy3LdNyZp5PCJWp65bWbsghE73jarsmhFQ4Q0oQQuB43mPtRGO3CCVxfuLcHzGqJqFo6g3WNqRY+nJvHz+lqppSdYqeQ/+ayfUgIlJqNtsNxio22xukLNf10/mBlCLOe0Dy4tmXLx8k5UPj5vqdQprMiuPpkbruuNm8YLd+QV21IOSlGlZe24+Pd3TdGqUUIXi65pr1za5szpsaoxu6ZoUQkmG6KNBUhbEtSkkWN1NXlq69Zn98Sza/lUF30wCaJAqDKMd06byVWoVWFqHaoi8SEzEmgpsgJfpxQsqI0S3IGaM6NvU16VJrUDqRs8OYxOF0Rsly3ZEy4/xEJQDhS3AxB1p9Tc4Go1tO04yPA5VpiTFjTfG6aVXhLqevm90zfCxe80xk1a0Yp54QB1ar3YU9lOiaK5zrQZUmtxKSxUUEGWu2GF0x+wNWZ6zuqHRHzgolDeuVZJwf0FoyLQOVkVTGMs1nlM4cTndlFT/X5BQKRF81IAI+wG73nBgSp/EOpRNaKFbtExCZfngooTVTIUXkPD2W5r26YdMYXDxckuFF9DhMPXUVv5PqVkqjpUFJSwyJfjwhVaJTa6wux2ejL9UHW5NTg7H2EnjN2HWZ+0hVaiVaa+Z55ubqRSm6RkdtN5fMi6CtS0p4cvsysPUDWc28uv+Urt7i4kLAcexHtrunOOfJwiNVREtJ3x9xzqO1QakWo1u0qEEnhqEEZaHULrruiphCaZxLQVVZIOH8CAiWeaHrtsXTtpwK2jVElKhQIrP4I4fTW6S0tG3F4s9FL94qcIXppSrDaXqgqlpimoshV0tkEqQ8M/WFVDm5e3yaWDU3qKwRwjO7O6wtI4fKVpQNeGazfYr3c0naS8l6dcPpdM/V9Q1uCZzPgXGMHE6fcBrvSThmP/L28WNi9uSUOY0Hpmni9d1HZSOdyvtJa1mkCQmcn9mfH0lCXjAohlcP38LocrWzesVxvCecFt7efxttKrLIWFvhwoKxFcN0xkfP69ef0Z9fk+MNr4Xk3B/Y7W6xuiKmpURORGJyZ+4/veP+8VMyC1nMbNYb6mpd8oCygSxp6xUhT9/7Q0koW7xNUbBqnxJijxCKWlmG8VDazKZDS8M8C5SuGIY9KS7085mmMZhN4QEvnAn+gNFr6qYm5YD3IyElKmsLfjMkpNRYo8sbWymUVpyHA53dkCP0yz0xR1ISGK1JQdI2a4K/nHqSuxDzDpesUaCtb2mqZ7jlY4zRl22AQmdB8BGp2sIfUhaBpFptcG6mqTp88BhREVG0dscw9khdkrdSl/pCTgklDOvmhpwdWczlGiBDGX7HGaUpCWVR0Tbm/9veuSxHlh3ZdZ33fQVemUWxKYlmPdD//4u+oK0pdrGqE5mIiPs6bw08SM1qQJm11QA+BwxA4Po9x33vtSk1c6S7/H11ojc5Eltr8X7AuQVUoiuNM5bJTHg/PryBO8EHaquYpjmOjRAuIkgNDhRM4xfoCrBkTmqP0tTsIPIFI4uGWgvUhNEj1/ud4B2tapbxhdZW4aTbIKv8vqG1eJisXiSnvjbCYLjf73Q6KRWMW8mlUHshhAnnRnJVjMuFkjv3VcyhWjeCv2BMIOYNP2iMsnQ6e/xGriPWKVHWP1zwMZ6PU3DGu+FhAzLU2lBKi90mGLS2KKWYpoEzCtBNGyvx40RCGFBaUlLoEmJgzYCzlRgTr88/cdaDUgu9J+IDRaKMBzLj6ABNKYlSuuB2cgXr6ErRaqeZyvePn5nnJxGeKk3wjm3fOc5fcSYQhpnzFGi/HzK//PjfKOXIbcX5jgsifbh+XFm3d4yvTFPgvv3K9verMdC6XIW1bo8gUcu6f6M3WPcr2lacVWKc9k90oJQTpQqtFt5vf8F5R0zxoddqpFSgNNb3X/D9ZDveGS4vfP/468Me1jDWUHLBeUutEIaO0qLVG8fp8YJ4ola5QRzxzn3d/vmmNE9fua/fGPwz3gXue8YYiGeklINUquBBGB/O8MbL6+Vx/Hwj50QYLkxtodbMGEZKzYL/LBmtNVOQULyUD5He9yZydDeilcMZjVLfiCmxjD9R4g+oUa45OaKUJ8VILqdA0JqmdkPpB7pGFLAfP3OmK9P4xhj+xHX7P5QcUdpw5pVlmDhTfnyohiG8YvxITNtjw+XQBFKS76fxDF497MwZawcGv5CTvD1rUWg34J1lngw5Z9bjyuvTH1BdsW2rGCfzldG/ktNJJZJKQemBVBrT+Mr19g1rLcZ0ajnZYqbWRyJwhv284awFLJf5mfOI9N44owxwb/crL5c/kMtBLCuD93zc/gYoZv9E642UTzGtGk3wA7klWi8c8UZrIhyNeWfbvjEvE70LwqP3yrr9Sq2JlIQ1pLTogIx5YG1bRzPg7Ezwch0o/YNUd7TmcY2dRfxaT3pttLqjtecy/0StknfmrCelyBkL4zAKn8uN1ArPyx/Yjx1MQSthUkHhPA8YQOmG8x3oaKceNAtpWtBxzsqVlUarSdT8PXPdf5ByxntHKZmc5es6mVIKy7KQU2aaHnqp1kBJoKnSGmOtIHBNp7VKqYKTSTliLJxHQiv3ABdCzSfjEFBqkKTnrgEvVNGasc5yufwLpUnaroRwAtaj6DIED/5xYlKS51bEmrQszyit2LZ3XpeZ/vgZrXmlty6sb+tJuTIGYaNL+tBGs4U//vnPLJc3cm1oY9HGyga9G6xVRB3Zjh8EF7gsT5RSGMJMLZ1xDPRWH+b5wtPlC87+fwy6P65/BToftxtn3BnCzPPyR6AQ/IRqha4atd9JqcrpgEZrF0mi6OI+NsbSmzwsWkNB0ncFRFYwzlB6IefM6D1nOqgZvH1iHt54Wf4ESvOx/kJDlKPBvUDXHPudVO8iMqxJQhCVpyOK4NozWmmcaezH90eGfWcKr9SaODmIMTKGgVwTpWY+br/i7QVrA+v+A+sG9uPG8/LlQQOQnC1rg/DEtw+8GygtQ1Oc+UYl4O3MfRVyo3OeFAtaneznB9tRMMZxxF1OAcPEeHmCbjjiFWvOh3ao07uhdEvpO/ux8+X5f+KtQxvNun3D+4HjWAl+oZQkm458p7HL9aNmznbjOHdKLRjrSDmz7d/xLmC0Yx5H9mPDWAGUOWvERnMWpmliGi44vdDplNwYp4Xv13dqSQQ/8LL8KzFmjvPfWLf/lJMKw4PXLC8OpQ1GB5wVooJRE6VGcmooBUOQ0+C6bZS2P0ByHwI40wZjG+bvymFlMMr9g2jYW2VwDqU6Ka2yGT4L3s+0rmTk0Cq1HTjnMWYU9TVgbXjMxmQ8ccSTUk6EJCCxYU2LTEGBvHiykSTmtMpDXMQ6pbxFdy8iwaYldaXrx1gi0WrHmccV0ZrHdq9zmV8k0NNURj9jjcI5iQI/451cb/Q6CEGyNvlcS6HUinOW0V8eWjT7WAA4iT0qojUqpbDMz3x5+h/sx4rxSmK0aWznB1BZgnhXu+ooupwGu8LaiVwqrR30nnle3nj/LonFIYijIIwS3nlZXjjjifNiNHZOcx53tBHfnOkC+Punm1JtkdYU2lS0aaR80Cm0riilMQQRKx7nHetEc6JV54w7pjZqy2idMU3A5Lo3ckzM45swhDvUnsmnJHlKjpxmCq8kFdEY7tuODzMp7WitaBWsncTIGDPOB+7rlWW+yKwjwzS98f37X7m8PNNVo+TMvm8oU8nnDd0mWoHWGubBKAruC7f7X8BUQJHbAbXQWkH1Ltn0KaIfsbm9i7VjP+9iu6mKI66SFGwUzgxM4xutC64l5UjNGbTIKmKKLLMkpVA1dC9cauvpyEq+9fZ4MDpDmIGFyzTQauPMV2o5WOYnziSBgjFGhjBjrZdBtRn49f3fGMZR9Crf/8bLywspRVKMxLzSGkzD+P8U1HYQ/pG13DdBz6ai0W2gFoNkx8+8/7hSquKyvLLerxx+44wn4/hMTD+wRtC7Snm0GVC6ksuGD4HajGxog0gUtGoykxsu3NcVaJxRCAZvL/+dWhVnvAnhwI0orYgxE2sSPZmVJoWGUhLOW1qrnPGQ+CLvua7vWCf6Lu8mVB+xpnLEVV4YSThTVWuMNqQSpZH1zjxKEi1K0/vAZZrY95W1fheNmZYmX2rHWiEdgNA4a4s4F/6xjT2OEzCMwytnPJmWC6WcdBIhWHLbiSnKaThtaP0Q4caTEAJaO3qO1FboSoSyKWcGpx+ugiRhHsyCrWkbpVXonXl648wbpW/o5sCO7Mcqg+gh0LVEYv09Hy+ngvcB4zypJox17Mc77x87Z44s8ysoOM8rnYY1Tuw+tbB+/IUQRkijMLK6QqnKx+3bY/74TzYlQeUmelfyw7bIj9tfqA2GceS2ClK0N43VoktxYeKMB2NwnEclxSz+oeGCorLM4+OIDdbJYLs1JQydXlnPO25wzMOrQPtLIaZKLRXnJmrvlFbo+aC0E9sn3i5vWBc4U8H7xnZemS5PaLyoWbvGuYFYV2iVaVjY48ZZNsbgOc6DNVyZlxdiOh+NSBHzxjRMjNNETrLZA43GMQzCHpqDDO9z2bFOFMPBvdB74/vHv0PXMGq0snQtKNSXp69sxx1jFJqR58vjBNJO0PXB9ZHPoJQoaR5NE4/K8+VPpBqpPeP8M1p1epU5mnYWaLSq4PE7q4dswOiRcVxoTYiiSsM0/PTwD47UdrJuMqA3JnCeieCeiemD/Tjo7cSaE2cv9CaBCq+XrzhjKSGxnr9wHjs/DX8mdeFf5XqnFon5DiGQSiPGDbrH+yeMhjG8yvUyZ479xDqROtRWhY7YJXTUuwXnrQDw1xUe/28hLJznIUkiXa4XvWSOXRC5uVUB7bmAsx7nxHqS1RXvRubhmT2uhEGSYOQqBoMPQoEsJ0pb0oMAEMIsD31PWA3T9MrtfpNgxhKFAeYqe44YVSmlyjPUOpdZAhhUEfSMt5rv1+9oXWi98Pb8hXLexZKkDOvxnXl+Zd8yxhrompwT+y7oYWM80/AqUeEqYZ2c3J2N3O83nJfDgHOGUgrxzEIH1RE9vbEfhVg3lNacpyyPvB+w2mLNQGngmqLkHa0U1iiskc/maXkCFVn3OzHtkinXC2fceX16ZTgcKMceP0g5clmeKbXhnaOU34a8/Ta6pHV6kyMtViTu2iiGYZb0iNHJjKFGaskMfsQZw9FWfny8Mw4z1jr2fePl8kcgU2rlPG44F0i5obWmlUrJkafnZ1LJbOdG9YqcK9PwhB881+s3Ss20CsZUnJ3J+aS0hKKTziwIBa2p7Y7SllwgppXL5YVaLMZaULDu74BicIGUBNE7hoXeDNuxgYbn8Y1cN+7HD8p6p5NBgXMv7Ospzm8Lc/jKen7nuv2C947Rf+GyfOU8D0KY2Y4b3z/+htJIaGYPYuL0IqFQylJLpZEwVq4Hzjl+fLyL1UEpznwl5orpXsyw6YZ9KJXv26+EEAhuAA0xipm0raeA0prC6IY25nEd1CzzTG+KeXoh1xOtFKXuWONJuWAblNxwNvD19c98u/5CbZF1e+fr64VleGawC7lmznJFK5h8YAojY3ijNc0ef6aTJXG2NWpVjMPC/X4VfxRw3z6AJnSHh/J3CBPbLkZVlIhwW0+P0EMZIRhr6SRRC4sCgFKK4Fq0ZXADqRQWc3k0xiyr7iY6NnrnSDdqE/a4NQZrF7b9xsftb7y+/DcZB+T2WFh0So8olZAvP1FapovX+5WUE9ZaxjDjrCVmQewM8ytDgBh3XDDctxthFF9h6415WKg9P/A3E7WK7o/eqaXxdPkjrQHqIOUs9inrmMY3kd4YR8qHAPxrprRITIVeKy4MyLay47TDaHmWl/GZVDeUnnleLvzH+7/z9e0r57Fxpo1l+gnVC+smbLPgnx6guZ1aC8v8lY/rN85eWGZLJ2BNx7vxIYnR3O4faC2LqH2/sVxmSqkY43i6/AvHsf/zTSmEmVJka6GaAgfezRgzPYh+mm17p1MZh0WuEufBZXnliIfAzrzcW4/0Q4SNLqA0HOcd72Yul68c7U5UO9fbDaccrVaOdAKa23bnGeFix3gwTQtKKeH7IDzvrYpeKTgZljvnUQq8C3ICWK+iTKWybTfmaSZFEWpa6+ld8XH9Js7/ctKBXe/ULgO7Tqa2SG8a3TthCJyx0Khct//Eh5Hnp6//QKuuj7WtMYbtvIkvzwh2ZJyeiOn8x8C4FLFZeO8Z3BP7fqUrhXOiZu5Vk+4n1jZGP1PaFWs7Rg2imfEVa42sw1XCGEtMK12JJqvmijUTJWdSKsyTbDGNccR4iIlzeaXkhsGQU8INlmUaSbkSk1zXsP7BDuoYN7Ce72znN+ZpYjALqMZ5Ru71F2qTY96+rZh5ebzEZGvlXUbpIqv0fOCcECe8U4RwkdBSP1D2O4MfGf3A9f4zpRTGcCGnA+cc3l9IMZHTSXAB7y1HlHhr6wzzMhJGhTIDZ9zEwV8PWsmEIFHlXXW6Fi748/IT637DjwOtVnovTIN7nO4OehMPZC6J7X7yp6//i+v+M8Z7gg7S2FRgDE/k8h8SsIliOzfOY8VXh+qGEEaMCpwxc/ZGq5lxWHBWXlbbXoX55EZyMtyP74TgqKlhrARGOOcoZccZReuFbb/R+989ZwM/1u9cljfBHpvK6EdS3jlbw1soXYHuXNcPnpYJVKL1zOAHvBZ+eSkf1A7r/We0bjwtF54uX6il8vwkoZlH2qk5M40Lg3ti3TdK2TnT9kD/BMIYqLWwlyvGDDw/XVAx/mZT+s00k8/6rM/6rP/q+k1G92d91md91n91fTalz/qsz/pd1WdT+qzP+qzfVX02pc/6rM/6XdVnU/qsz/qs31V9NqXP+qzP+l3V/wW1oV1q2rKCKAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Prepare input data\n", + "IMG_PATH = \"examples/img1.jpg\"\n", + "img = cv2.cvtColor(cv2.imread(IMG_PATH), cv2.COLOR_BGR2RGB)\n", + "org_h, org_w = img.shape[:2]\n", + "img_input = cv2.resize(img, (192, 256), interpolation=cv2.INTER_LINEAR)\n", + "img_input = img_input.astype(np.float32).transpose(2, 0, 1)[None, ...] / 255\n", + "\n", + "# Copy it into appropriate place into memory\n", + "# (inputs was returned earlier by allocate_buffers())\n", + "np.copyto(inputs[0].host, img_input.ravel())\n", + "\n", + "# Feed to model\n", + "tic = time()\n", + "bs = 1\n", + "# Fetch output from the model\n", + "heatmaps = engine_utils.do_inference(\n", + " context, bindings=bindings, inputs=inputs,\n", + " outputs=outputs, stream=stream)[0]\n", + "heatmaps = heatmaps.reshape((1, 25, 64, 48))\n", + "\n", + "elapsed_time = time()-tic\n", + "print(f\">>> Output size: {heatmaps.shape} ---> {elapsed_time:.4f} sec. elapsed [{elapsed_time**-1: .1f} fps]\\n\") \n", + "\n", + "points, prob = keypoints_from_heatmaps(heatmaps=heatmaps, center=np.array([[org_w//2, org_h//2]]), scale=np.array([[org_w, org_h]]),\n", + " unbiased=True, use_udp=True)\n", + "points = np.concatenate([points[:, :, ::-1], prob], axis=2)\n", + "\n", + "# Visualization \n", + "for pid, point in enumerate(points):\n", + " img = draw_points_and_skeleton(img.copy(), point, joints_dict()['coco']['skeleton'], person_index=pid,\n", + " points_color_palette='gist_rainbow', skeleton_color_palette='jet',\n", + " points_palette_samples=10, confidence_threshold=0.4)\n", + " \n", + " plt.figure(figsize=(5,10))\n", + " plt.imshow(img)\n", + " plt.title(\"Result\")\n", + " plt.axis('off')\n", + " plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.17" + }, + "vscode": { + "interpreter": { + "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/easy_ViTPose/train.py b/easy_ViTPose/train.py new file mode 100644 index 0000000000000000000000000000000000000000..8741b7e5d01f937012cbeb434f5362bbbb263b98 --- /dev/null +++ b/easy_ViTPose/train.py @@ -0,0 +1,174 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import copy +import os +import os.path as osp +import time +import warnings +import click +import yaml + +from glob import glob + +import torch +import torch.distributed as dist + +from vit_utils.util import init_random_seed, set_random_seed +from vit_utils.dist_util import get_dist_info, init_dist +from vit_utils.logging import get_root_logger + +import configs.ViTPose_small_coco_256x192 as s_cfg +import configs.ViTPose_base_coco_256x192 as b_cfg +import configs.ViTPose_large_coco_256x192 as l_cfg +import configs.ViTPose_huge_coco_256x192 as h_cfg + +from vit_models.model import ViTPose +from datasets.COCO import COCODataset +from vit_utils.train_valid_fn import train_model + +CUR_PATH = osp.dirname(__file__) + +@click.command() +@click.option('--config-path', type=click.Path(exists=True), default='config.yaml', required=True, help='train config file path') +@click.option('--model-name', type=str, default='b', required=True, help='[b: ViT-B, l: ViT-L, h: ViT-H]') +def main(config_path, model_name): + + cfg = {'b':b_cfg, + 's':s_cfg, + 'l':l_cfg, + 'h':h_cfg}.get(model_name.lower()) + # Load config.yaml + with open(config_path, 'r') as f: + cfg_yaml = yaml.load(f, Loader=yaml.SafeLoader) + + for k, v in cfg_yaml.items(): + if hasattr(cfg, k): + raise ValueError(f"Already exists {k} in config") + else: + cfg.__setattr__(k, v) + + # set cudnn_benchmark + if cfg.cudnn_benchmark: + torch.backends.cudnn.benchmark = True + + # Set work directory (session-level) + if not hasattr(cfg, 'work_dir'): + cfg.__setattr__('work_dir', f"{CUR_PATH}/runs/train") + + if not osp.exists(cfg.work_dir): + os.makedirs(cfg.work_dir) + session_list = sorted(glob(f"{cfg.work_dir}/*")) + if len(session_list) == 0: + session = 1 + else: + session = int(os.path.basename(session_list[-1])) + 1 + session_dir = osp.join(cfg.work_dir, str(session).zfill(3)) + os.makedirs(session_dir) + cfg.__setattr__('work_dir', session_dir) + + + if cfg.autoscale_lr: + # apply the linear scaling rule (https://arxiv.org/abs/1706.02677) + cfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8 + + # init distributed env first, since logger depends on the dist info. + if cfg.launcher == 'none': + distributed = False + if len(cfg.gpu_ids) > 1: + warnings.warn( + f"We treat {cfg['gpu_ids']} as gpu-ids, and reset to " + f"{cfg['gpu_ids'][0:1]} as gpu-ids to avoid potential error in " + "non-distribute training time.") + cfg.gpu_ids = cfg.gpu_ids[0:1] + else: + distributed = True + init_dist(cfg.launcher, **cfg.dist_params) + # re-set gpu_ids with distributed training mode + _, world_size = get_dist_info() + cfg.gpu_ids = range(world_size) + + # init the logger before other steps + timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) + log_file = osp.join(session_dir, f'{timestamp}.log') + logger = get_root_logger(log_file=log_file) + + # init the meta dict to record some important information such as + # environment info and seed, which will be logged + meta = dict() + + # log some basic info + logger.info(f'Distributed training: {distributed}') + + # set random seeds + seed = init_random_seed(cfg.seed) + logger.info(f"Set random seed to {seed}, " + f"deterministic: {cfg.deterministic}") + set_random_seed(seed, deterministic=cfg.deterministic) + meta['seed'] = seed + + # Set model + model = ViTPose(cfg.model) + if cfg.resume_from: + # Load ckpt partially + ckpt_state = torch.load(cfg.resume_from)['state_dict'] + ckpt_state.pop('keypoint_head.final_layer.bias') + ckpt_state.pop('keypoint_head.final_layer.weight') + model.load_state_dict(ckpt_state, strict=False) + + # freeze the backbone, leave the head to be finetuned + model.backbone.frozen_stages = model.backbone.depth - 1 + model.backbone.freeze_ffn = True + model.backbone.freeze_attn = True + model.backbone._freeze_stages() + + # Set dataset + datasets_train = COCODataset( + root_path=cfg.data_root, + data_version="feet_train", + is_train=True, + use_gt_bboxes=True, + image_width=192, + image_height=256, + scale=True, + scale_factor=0.35, + flip_prob=0.5, + rotate_prob=0.5, + rotation_factor=45., + half_body_prob=0.3, + use_different_joints_weight=True, + heatmap_sigma=3, + soft_nms=False + ) + + datasets_valid = COCODataset( + root_path=cfg.data_root, + data_version="feet_val", + is_train=False, + use_gt_bboxes=True, + image_width=192, + image_height=256, + scale=False, + scale_factor=0.35, + flip_prob=0.5, + rotate_prob=0.5, + rotation_factor=45., + half_body_prob=0.3, + use_different_joints_weight=True, + heatmap_sigma=3, + soft_nms=False + ) + + train_model( + model=model, + datasets_train=datasets_train, + datasets_valid=datasets_valid, + cfg=cfg, + distributed=distributed, + validate=cfg.validate, + timestamp=timestamp, + meta=meta + ) + + +if __name__ == '__main__': + main() diff --git a/easy_ViTPose/vit_models/__init__.py b/easy_ViTPose/vit_models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1142f43bfb07009a49120d7aceb711fb349bd8f1 --- /dev/null +++ b/easy_ViTPose/vit_models/__init__.py @@ -0,0 +1,8 @@ +import sys +import os.path as osp + +sys.path.append(osp.dirname(osp.dirname(__file__))) + +from vit_utils.util import load_checkpoint, resize, constant_init, normal_init +from vit_utils.top_down_eval import keypoints_from_heatmaps, pose_pck_accuracy +from vit_utils.post_processing import * diff --git a/easy_ViTPose/vit_models/backbone/__init__.py b/easy_ViTPose/vit_models/backbone/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/easy_ViTPose/vit_models/backbone/vit.py b/easy_ViTPose/vit_models/backbone/vit.py new file mode 100644 index 0000000000000000000000000000000000000000..74d7bee914e5a08a925e127f13243d22c0af6daf --- /dev/null +++ b/easy_ViTPose/vit_models/backbone/vit.py @@ -0,0 +1,394 @@ + +import math +import warnings + +from itertools import repeat +import collections.abc + +import torch +from functools import partial +import torch.nn as nn +import torch.nn.functional as F +import torch.utils.checkpoint as checkpoint +from torch import Tensor + +# from timm.models.layers import drop_path, to_2tuple, trunc_normal_ + +# from .base_backbone import BaseBackbone + +def drop_path(x, drop_prob: float = 0., training: bool = False, scale_by_keep: bool = True): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + + This is the same as the DropConnect impl I created for EfficientNet, etc networks, however, + the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper... + See discussion: https://github.com/tensorflow/tpu/issues/494#issuecomment-532968956 ... I've opted for + changing the layer and argument names to 'drop path' rather than mix DropConnect as a layer name and use + 'survival rate' as the argument. + + """ + if drop_prob == 0. or not training: + return x + keep_prob = 1 - drop_prob + shape = (x.shape[0],) + (1,) * (x.ndim - 1) # work with diff dim tensors, not just 2D ConvNets + random_tensor = x.new_empty(shape).bernoulli_(keep_prob) + if keep_prob > 0.0 and scale_by_keep: + random_tensor.div_(keep_prob) + return x * random_tensor + +def _ntuple(n): + def parse(x): + if isinstance(x, collections.abc.Iterable) and not isinstance(x, str): + return x + return tuple(repeat(x, n)) + return parse + + +to_1tuple = _ntuple(1) +to_2tuple = _ntuple(2) +to_3tuple = _ntuple(3) +to_4tuple = _ntuple(4) +to_ntuple = _ntuple + +def _trunc_normal_(tensor, mean, std, a, b): + # Cut & paste from PyTorch official master until it's in a few official releases - RW + # Method based on https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdf + def norm_cdf(x): + # Computes standard normal cumulative distribution function + return (1. + math.erf(x / math.sqrt(2.))) / 2. + + if (mean < a - 2 * std) or (mean > b + 2 * std): + warnings.warn("mean is more than 2 std from [a, b] in nn.init.trunc_normal_. " + "The distribution of values may be incorrect.", + stacklevel=2) + + # Values are generated by using a truncated uniform distribution and + # then using the inverse CDF for the normal distribution. + # Get upper and lower cdf values + l = norm_cdf((a - mean) / std) + u = norm_cdf((b - mean) / std) + + # Uniformly fill tensor with values from [l, u], then translate to + # [2l-1, 2u-1]. + tensor.uniform_(2 * l - 1, 2 * u - 1) + + # Use inverse cdf transform for normal distribution to get truncated + # standard normal + tensor.erfinv_() + + # Transform to proper mean, std + tensor.mul_(std * math.sqrt(2.)) + tensor.add_(mean) + + # Clamp to ensure it's in the proper range + tensor.clamp_(min=a, max=b) + return tensor + + +def trunc_normal_(tensor, mean=0., std=1., a=-2., b=2.): + # type: (Tensor, float, float, float, float) -> Tensor + r"""Fills the input Tensor with values drawn from a truncated + normal distribution. The values are effectively drawn from the + normal distribution :math:`\mathcal{N}(\text{mean}, \text{std}^2)` + with values outside :math:`[a, b]` redrawn until they are within + the bounds. The method used for generating the random values works + best when :math:`a \leq \text{mean} \leq b`. + + NOTE: this impl is similar to the PyTorch trunc_normal_, the bounds [a, b] are + applied while sampling the normal with mean/std applied, therefore a, b args + should be adjusted to match the range of mean, std args. + + Args: + tensor: an n-dimensional `torch.Tensor` + mean: the mean of the normal distribution + std: the standard deviation of the normal distribution + a: the minimum cutoff value + b: the maximum cutoff value + Examples: + >>> w = torch.empty(3, 5) + >>> nn.init.trunc_normal_(w) + """ + with torch.no_grad(): + return _trunc_normal_(tensor, mean, std, a, b) + +class DropPath(nn.Module): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + """ + def __init__(self, drop_prob=None): + super(DropPath, self).__init__() + self.drop_prob = drop_prob + + def forward(self, x): + return drop_path(x, self.drop_prob, self.training) + + def extra_repr(self): + return 'p={}'.format(self.drop_prob) + +class Mlp(nn.Module): + def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.fc1 = nn.Linear(in_features, hidden_features) + self.act = act_layer() + self.fc2 = nn.Linear(hidden_features, out_features) + self.drop = nn.Dropout(drop) + + def forward(self, x): + x = self.fc1(x) + x = self.act(x) + x = self.fc2(x) + x = self.drop(x) + return x + +class Attention(nn.Module): + def __init__( + self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., + proj_drop=0., attn_head_dim=None,): + super().__init__() + self.num_heads = num_heads + head_dim = dim // num_heads + self.dim = dim + + if attn_head_dim is not None: + head_dim = attn_head_dim + all_head_dim = head_dim * self.num_heads + + self.scale = qk_scale or head_dim ** -0.5 + + self.qkv = nn.Linear(dim, all_head_dim * 3, bias=qkv_bias) + + self.attn_drop = nn.Dropout(attn_drop) + self.proj = nn.Linear(all_head_dim, dim) + self.proj_drop = nn.Dropout(proj_drop) + + def forward(self, x): + B, N, C = x.shape + qkv = self.qkv(x) + qkv = qkv.reshape(B, N, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4) + q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple) + + q = q * self.scale + attn = (q @ k.transpose(-2, -1)) + + attn = attn.softmax(dim=-1) + attn = self.attn_drop(attn) + + x = (attn @ v).transpose(1, 2).reshape(B, N, -1) + x = self.proj(x) + x = self.proj_drop(x) + + return x + +class Block(nn.Module): + + def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, + drop=0., attn_drop=0., drop_path=0., act_layer=nn.GELU, + norm_layer=nn.LayerNorm, attn_head_dim=None + ): + super().__init__() + + self.norm1 = norm_layer(dim) + self.attn = Attention( + dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, + attn_drop=attn_drop, proj_drop=drop, attn_head_dim=attn_head_dim + ) + + # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here + self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity() + self.norm2 = norm_layer(dim) + mlp_hidden_dim = int(dim * mlp_ratio) + self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop) + + def forward(self, x): + x = x + self.drop_path(self.attn(self.norm1(x))) + x = x + self.drop_path(self.mlp(self.norm2(x))) + return x + + +class PatchEmbed(nn.Module): + """ Image to Patch Embedding + """ + def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768, ratio=1): + super().__init__() + img_size = to_2tuple(img_size) + patch_size = to_2tuple(patch_size) + num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // patch_size[0]) * (ratio ** 2) + self.patch_shape = (int(img_size[0] // patch_size[0] * ratio), int(img_size[1] // patch_size[1] * ratio)) + self.origin_patch_shape = (int(img_size[0] // patch_size[0]), int(img_size[1] // patch_size[1])) + self.img_size = img_size + self.patch_size = patch_size + self.num_patches = num_patches + + self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=(patch_size[0] // ratio), padding=4 + 2 * (ratio//2-1)) + + def forward(self, x): + x = self.proj(x) + B, C, Hp, Wp = x.shape + x = x.view(B, C, Hp * Wp).transpose(1, 2) + return x, (Hp, Wp) + + +class HybridEmbed(nn.Module): + """ CNN Feature Map Embedding + Extract feature map from CNN, flatten, project to embedding dim. + """ + def __init__(self, backbone, img_size=224, feature_size=None, in_chans=3, embed_dim=768): + super().__init__() + assert isinstance(backbone, nn.Module) + img_size = to_2tuple(img_size) + self.img_size = img_size + self.backbone = backbone + if feature_size is None: + with torch.no_grad(): + training = backbone.training + if training: + backbone.eval() + o = self.backbone(torch.zeros(1, in_chans, img_size[0], img_size[1]))[-1] + feature_size = o.shape[-2:] + feature_dim = o.shape[1] + backbone.train(training) + else: + feature_size = to_2tuple(feature_size) + feature_dim = self.backbone.feature_info.channels()[-1] + self.num_patches = feature_size[0] * feature_size[1] + self.proj = nn.Linear(feature_dim, embed_dim) + + def forward(self, x): + x = self.backbone(x)[-1] + x = x.flatten(2).transpose(1, 2) + x = self.proj(x) + return x + + +class ViT(nn.Module): + def __init__(self, + img_size=224, patch_size=16, in_chans=3, num_classes=80, embed_dim=768, depth=12, + num_heads=12, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop_rate=0., attn_drop_rate=0., + drop_path_rate=0., hybrid_backbone=None, norm_layer=None, use_checkpoint=False, + frozen_stages=-1, ratio=1, last_norm=True, + patch_padding='pad', freeze_attn=False, freeze_ffn=False, + ): + super(ViT, self).__init__() + # Protect mutable default arguments + + norm_layer = norm_layer or partial(nn.LayerNorm, eps=1e-6) + self.num_classes = num_classes + self.num_features = self.embed_dim = embed_dim # num_features for consistency with other models + self.frozen_stages = frozen_stages + self.use_checkpoint = use_checkpoint + self.patch_padding = patch_padding + self.freeze_attn = freeze_attn + self.freeze_ffn = freeze_ffn + self.depth = depth + + if hybrid_backbone is not None: + self.patch_embed = HybridEmbed( + hybrid_backbone, img_size=img_size, in_chans=in_chans, embed_dim=embed_dim) + else: + self.patch_embed = PatchEmbed( + img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim, ratio=ratio) + num_patches = self.patch_embed.num_patches + + # since the pretraining model has class token + self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim)) + + dpr = [x.item() for x in torch.linspace(0, drop_path_rate, depth)] # stochastic depth decay rule + + self.blocks = nn.ModuleList([ + Block( + dim=embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale, + drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i], norm_layer=norm_layer, + ) + for i in range(depth)]) + + self.last_norm = norm_layer(embed_dim) if last_norm else nn.Identity() + + if self.pos_embed is not None: + trunc_normal_(self.pos_embed, std=.02) + + self._freeze_stages() + + def _freeze_stages(self): + """Freeze parameters.""" + if self.frozen_stages >= 0: + self.patch_embed.eval() + for param in self.patch_embed.parameters(): + param.requires_grad = False + + for i in range(1, self.frozen_stages + 1): + m = self.blocks[i] + m.eval() + for param in m.parameters(): + param.requires_grad = False + + if self.freeze_attn: + for i in range(0, self.depth): + m = self.blocks[i] + m.attn.eval() + m.norm1.eval() + for param in m.attn.parameters(): + param.requires_grad = False + for param in m.norm1.parameters(): + param.requires_grad = False + + if self.freeze_ffn: + self.pos_embed.requires_grad = False + self.patch_embed.eval() + for param in self.patch_embed.parameters(): + param.requires_grad = False + for i in range(0, self.depth): + m = self.blocks[i] + m.mlp.eval() + m.norm2.eval() + for param in m.mlp.parameters(): + param.requires_grad = False + for param in m.norm2.parameters(): + param.requires_grad = False + + def init_weights(self, pretrained=None): + """Initialize the weights in backbone. + Args: + pretrained (str, optional): Path to pre-trained weights. + Defaults to None. + """ + super().init_weights(pretrained, patch_padding=self.patch_padding) + + if pretrained is None: + def _init_weights(m): + if isinstance(m, nn.Linear): + trunc_normal_(m.weight, std=.02) + if isinstance(m, nn.Linear) and m.bias is not None: + nn.init.constant_(m.bias, 0) + elif isinstance(m, nn.LayerNorm): + nn.init.constant_(m.bias, 0) + nn.init.constant_(m.weight, 1.0) + + self.apply(_init_weights) + + def get_num_layers(self): + return len(self.blocks) + + @torch.jit.ignore + def no_weight_decay(self): + return {'pos_embed', 'cls_token'} + + def forward(self, x): + B, C, H, W = x.shape + x, (Hp, Wp) = self.patch_embed(x) + + if self.pos_embed is not None: + # fit for multiple GPU training + # since the first element for pos embed (sin-cos manner) is zero, it will cause no difference + x = x + self.pos_embed[:, 1:] + self.pos_embed[:, :1] + + for blk in self.blocks: + x = blk(x) + + x = self.last_norm(x) + x = x.permute(0, 2, 1).view(B, -1, Hp, Wp).contiguous() + return x + + def train(self, mode=True): + """Convert the model into training mode.""" + super().train(mode) + self._freeze_stages() diff --git a/easy_ViTPose/vit_models/head/__init__.py b/easy_ViTPose/vit_models/head/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/easy_ViTPose/vit_models/head/topdown_heatmap_base_head.py b/easy_ViTPose/vit_models/head/topdown_heatmap_base_head.py new file mode 100644 index 0000000000000000000000000000000000000000..e7a4138bf252d3efbfe939d8fee66edecfa2bbd9 --- /dev/null +++ b/easy_ViTPose/vit_models/head/topdown_heatmap_base_head.py @@ -0,0 +1,120 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from abc import ABCMeta, abstractmethod + +import numpy as np +import torch.nn as nn + +from .. import keypoints_from_heatmaps + + +class TopdownHeatmapBaseHead(nn.Module): + """Base class for top-down heatmap heads. + + All top-down heatmap heads should subclass it. + All subclass should overwrite: + + Methods:`get_loss`, supporting to calculate loss. + Methods:`get_accuracy`, supporting to calculate accuracy. + Methods:`forward`, supporting to forward model. + Methods:`inference_model`, supporting to inference model. + """ + + __metaclass__ = ABCMeta + + @abstractmethod + def get_loss(self, **kwargs): + """Gets the loss.""" + + @abstractmethod + def get_accuracy(self, **kwargs): + """Gets the accuracy.""" + + @abstractmethod + def forward(self, **kwargs): + """Forward function.""" + + @abstractmethod + def inference_model(self, **kwargs): + """Inference function.""" + + def decode(self, img_metas, output, **kwargs): + """Decode keypoints from heatmaps. + + Args: + img_metas (list(dict)): Information about data augmentation + By default this includes: + + - "image_file: path to the image file + - "center": center of the bbox + - "scale": scale of the bbox + - "rotation": rotation of the bbox + - "bbox_score": score of bbox + output (np.ndarray[N, K, H, W]): model predicted heatmaps. + """ + batch_size = len(img_metas) + + if 'bbox_id' in img_metas[0]: + bbox_ids = [] + else: + bbox_ids = None + + c = np.zeros((batch_size, 2), dtype=np.float32) + s = np.zeros((batch_size, 2), dtype=np.float32) + image_paths = [] + score = np.ones(batch_size) + for i in range(batch_size): + c[i, :] = img_metas[i]['center'] + s[i, :] = img_metas[i]['scale'] + image_paths.append(img_metas[i]['image_file']) + + if 'bbox_score' in img_metas[i]: + score[i] = np.array(img_metas[i]['bbox_score']).reshape(-1) + if bbox_ids is not None: + bbox_ids.append(img_metas[i]['bbox_id']) + + preds, maxvals = keypoints_from_heatmaps( + output, + c, + s, + unbiased=self.test_cfg.get('unbiased_decoding', False), + post_process=self.test_cfg.get('post_process', 'default'), + kernel=self.test_cfg.get('modulate_kernel', 11), + valid_radius_factor=self.test_cfg.get('valid_radius_factor', + 0.0546875), + use_udp=self.test_cfg.get('use_udp', False), + target_type=self.test_cfg.get('target_type', 'GaussianHeatmap')) + + all_preds = np.zeros((batch_size, preds.shape[1], 3), dtype=np.float32) + all_boxes = np.zeros((batch_size, 6), dtype=np.float32) + all_preds[:, :, 0:2] = preds[:, :, 0:2] + all_preds[:, :, 2:3] = maxvals + all_boxes[:, 0:2] = c[:, 0:2] + all_boxes[:, 2:4] = s[:, 0:2] + all_boxes[:, 4] = np.prod(s * 200.0, axis=1) + all_boxes[:, 5] = score + + result = {} + + result['preds'] = all_preds + result['boxes'] = all_boxes + result['image_paths'] = image_paths + result['bbox_ids'] = bbox_ids + + return result + + @staticmethod + def _get_deconv_cfg(deconv_kernel): + """Get configurations for deconv layers.""" + if deconv_kernel == 4: + padding = 1 + output_padding = 0 + elif deconv_kernel == 3: + padding = 1 + output_padding = 1 + elif deconv_kernel == 2: + padding = 0 + output_padding = 0 + else: + raise ValueError(f'Not supported num_kernels ({deconv_kernel}).') + + return deconv_kernel, padding, output_padding diff --git a/easy_ViTPose/vit_models/head/topdown_heatmap_simple_head.py b/easy_ViTPose/vit_models/head/topdown_heatmap_simple_head.py new file mode 100644 index 0000000000000000000000000000000000000000..2a7d63f579a6b34035f99dd75fb138f2e1997df3 --- /dev/null +++ b/easy_ViTPose/vit_models/head/topdown_heatmap_simple_head.py @@ -0,0 +1,334 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import torch +import torch.nn as nn +from .. import constant_init, normal_init + +from .. import pose_pck_accuracy, flip_back, resize +import torch.nn.functional as F +from .topdown_heatmap_base_head import TopdownHeatmapBaseHead + + +class TopdownHeatmapSimpleHead(TopdownHeatmapBaseHead): + """Top-down heatmap simple head. paper ref: Bin Xiao et al. ``Simple + Baselines for Human Pose Estimation and Tracking``. + + TopdownHeatmapSimpleHead is consisted of (>=0) number of deconv layers + and a simple conv2d layer. + + Args: + in_channels (int): Number of input channels + out_channels (int): Number of output channels + num_deconv_layers (int): Number of deconv layers. + num_deconv_layers should >= 0. Note that 0 means + no deconv layers. + num_deconv_filters (list|tuple): Number of filters. + If num_deconv_layers > 0, the length of + num_deconv_kernels (list|tuple): Kernel sizes. + in_index (int|Sequence[int]): Input feature index. Default: 0 + input_transform (str|None): Transformation type of input features. + Options: 'resize_concat', 'multiple_select', None. + Default: None. + + - 'resize_concat': Multiple feature maps will be resized to the + same size as the first one and then concat together. + Usually used in FCN head of HRNet. + - 'multiple_select': Multiple feature maps will be bundle into + a list and passed into decode head. + - None: Only one select feature map is allowed. + align_corners (bool): align_corners argument of F.interpolate. + Default: False. + loss_keypoint (dict): Config for keypoint loss. Default: None. + """ + + def __init__(self, + in_channels, + out_channels, + num_deconv_layers=3, + num_deconv_filters=(256, 256, 256), + num_deconv_kernels=(4, 4, 4), + extra=None, + in_index=0, + input_transform=None, + align_corners=False, + loss_keypoint=None, + train_cfg=None, + test_cfg=None, + upsample=0,): + super().__init__() + + self.in_channels = in_channels + self.loss = loss_keypoint + self.upsample = upsample + + self.train_cfg = {} if train_cfg is None else train_cfg + self.test_cfg = {} if test_cfg is None else test_cfg + self.target_type = self.test_cfg.get('target_type', 'GaussianHeatmap') + + self._init_inputs(in_channels, in_index, input_transform) + self.in_index = in_index + self.align_corners = align_corners + + if extra is not None and not isinstance(extra, dict): + raise TypeError('extra should be dict or None.') + + if num_deconv_layers > 0: + self.deconv_layers = self._make_deconv_layer( + num_deconv_layers, + num_deconv_filters, + num_deconv_kernels, + ) + elif num_deconv_layers == 0: + self.deconv_layers = nn.Identity() + else: + raise ValueError( + f'num_deconv_layers ({num_deconv_layers}) should >= 0.') + + identity_final_layer = False + if extra is not None and 'final_conv_kernel' in extra: + assert extra['final_conv_kernel'] in [0, 1, 3] + if extra['final_conv_kernel'] == 3: + padding = 1 + elif extra['final_conv_kernel'] == 1: + padding = 0 + else: + # 0 for Identity mapping. + identity_final_layer = True + kernel_size = extra['final_conv_kernel'] + else: + kernel_size = 1 + padding = 0 + + if identity_final_layer: + self.final_layer = nn.Identity() + else: + conv_channels = num_deconv_filters[ + -1] if num_deconv_layers > 0 else self.in_channels + + layers = [] + if extra is not None: + num_conv_layers = extra.get('num_conv_layers', 0) + num_conv_kernels = extra.get('num_conv_kernels', + [1] * num_conv_layers) + + for i in range(num_conv_layers): + layers.append( + nn.Conv2d(in_channels=conv_channels, + out_channels=conv_channels, + kernel_size=num_conv_kernels[i], + stride=1, + padding=(num_conv_kernels[i] - 1) // 2) + ) + layers.append(nn.BatchNorm2d(conv_channels)) + layers.append(nn.ReLU(inplace=True)) + + layers.append( + nn.Conv2d(in_channels=conv_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=1, + padding=padding) + ) + + if len(layers) > 1: + self.final_layer = nn.Sequential(*layers) + else: + self.final_layer = layers[0] + + def get_loss(self, output, target, target_weight): + """Calculate top-down keypoint loss. + + Note: + - batch_size: N + - num_keypoints: K + - heatmaps height: H + - heatmaps weight: W + + Args: + output (torch.Tensor[N,K,H,W]): Output heatmaps. + target (torch.Tensor[N,K,H,W]): Target heatmaps. + target_weight (torch.Tensor[N,K,1]): + Weights across different joint types. + """ + + losses = dict() + + assert not isinstance(self.loss, nn.Sequential) + assert target.dim() == 4 and target_weight.dim() == 3 + losses['heatmap_loss'] = self.loss(output, target, target_weight) + + return losses + + def get_accuracy(self, output, target, target_weight): + """Calculate accuracy for top-down keypoint loss. + + Note: + - batch_size: N + - num_keypoints: K + - heatmaps height: H + - heatmaps weight: W + + Args: + output (torch.Tensor[N,K,H,W]): Output heatmaps. + target (torch.Tensor[N,K,H,W]): Target heatmaps. + target_weight (torch.Tensor[N,K,1]): + Weights across different joint types. + """ + + accuracy = dict() + + if self.target_type == 'GaussianHeatmap': + _, avg_acc, _ = pose_pck_accuracy( + output.detach().cpu().numpy(), + target.detach().cpu().numpy(), + target_weight.detach().cpu().numpy().squeeze(-1) > 0) + accuracy['acc_pose'] = float(avg_acc) + + return accuracy + + def forward(self, x): + """Forward function.""" + x = self._transform_inputs(x) + x = self.deconv_layers(x) + x = self.final_layer(x) + return x + + def inference_model(self, x, flip_pairs=None): + """Inference function. + + Returns: + output_heatmap (np.ndarray): Output heatmaps. + + Args: + x (torch.Tensor[N,K,H,W]): Input features. + flip_pairs (None | list[tuple]): + Pairs of keypoints which are mirrored. + """ + output = self.forward(x) + + if flip_pairs is not None: + output_heatmap = flip_back( + output.detach().cpu().numpy(), + flip_pairs, + target_type=self.target_type) + # feature is not aligned, shift flipped heatmap for higher accuracy + if self.test_cfg.get('shift_heatmap', False): + output_heatmap[:, :, :, 1:] = output_heatmap[:, :, :, :-1] + else: + output_heatmap = output.detach().cpu().numpy() + return output_heatmap + + def _init_inputs(self, in_channels, in_index, input_transform): + """Check and initialize input transforms. + + The in_channels, in_index and input_transform must match. + Specifically, when input_transform is None, only single feature map + will be selected. So in_channels and in_index must be of type int. + When input_transform is not None, in_channels and in_index must be + list or tuple, with the same length. + + Args: + in_channels (int|Sequence[int]): Input channels. + in_index (int|Sequence[int]): Input feature index. + input_transform (str|None): Transformation type of input features. + Options: 'resize_concat', 'multiple_select', None. + + - 'resize_concat': Multiple feature maps will be resize to the + same size as first one and than concat together. + Usually used in FCN head of HRNet. + - 'multiple_select': Multiple feature maps will be bundle into + a list and passed into decode head. + - None: Only one select feature map is allowed. + """ + + if input_transform is not None: + assert input_transform in ['resize_concat', 'multiple_select'] + self.input_transform = input_transform + self.in_index = in_index + if input_transform is not None: + assert isinstance(in_channels, (list, tuple)) + assert isinstance(in_index, (list, tuple)) + assert len(in_channels) == len(in_index) + if input_transform == 'resize_concat': + self.in_channels = sum(in_channels) + else: + self.in_channels = in_channels + else: + assert isinstance(in_channels, int) + assert isinstance(in_index, int) + self.in_channels = in_channels + + def _transform_inputs(self, inputs): + """Transform inputs for decoder. + + Args: + inputs (list[Tensor] | Tensor): multi-level img features. + + Returns: + Tensor: The transformed inputs + """ + if not isinstance(inputs, list): + if self.upsample > 0: + raise NotImplementedError + return inputs + + if self.input_transform == 'resize_concat': + inputs = [inputs[i] for i in self.in_index] + upsampled_inputs = [ + resize( + input=x, + size=inputs[0].shape[2:], + mode='bilinear', + align_corners=self.align_corners) for x in inputs + ] + inputs = torch.cat(upsampled_inputs, dim=1) + elif self.input_transform == 'multiple_select': + inputs = [inputs[i] for i in self.in_index] + else: + inputs = inputs[self.in_index] + + return inputs + + def _make_deconv_layer(self, num_layers, num_filters, num_kernels): + """Make deconv layers.""" + if num_layers != len(num_filters): + error_msg = f'num_layers({num_layers}) ' \ + f'!= length of num_filters({len(num_filters)})' + raise ValueError(error_msg) + if num_layers != len(num_kernels): + error_msg = f'num_layers({num_layers}) ' \ + f'!= length of num_kernels({len(num_kernels)})' + raise ValueError(error_msg) + + layers = [] + for i in range(num_layers): + kernel, padding, output_padding = \ + self._get_deconv_cfg(num_kernels[i]) + + planes = num_filters[i] + layers.append( + nn.ConvTranspose2d(in_channels=self.in_channels, + out_channels=planes, + kernel_size=kernel, + stride=2, + padding=padding, + output_padding=output_padding, + bias=False) + ) + layers.append(nn.BatchNorm2d(planes)) + layers.append(nn.ReLU(inplace=True)) + self.in_channels = planes + + return nn.Sequential(*layers) + + def init_weights(self): + """Initialize model weights.""" + for _, m in self.deconv_layers.named_modules(): + if isinstance(m, nn.ConvTranspose2d): + normal_init(m, std=0.001) + elif isinstance(m, nn.BatchNorm2d): + constant_init(m, 1) + for m in self.final_layer.modules(): + if isinstance(m, nn.Conv2d): + normal_init(m, std=0.001, bias=0) + elif isinstance(m, nn.BatchNorm2d): + constant_init(m, 1) diff --git a/easy_ViTPose/vit_models/losses/__init__.py b/easy_ViTPose/vit_models/losses/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d67973fc5cb53e85faa918719944d8c02f2190cd --- /dev/null +++ b/easy_ViTPose/vit_models/losses/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from .classfication_loss import BCELoss +from .heatmap_loss import AdaptiveWingLoss +from .mesh_loss import GANLoss, MeshLoss +from .mse_loss import JointsMSELoss, JointsOHKMMSELoss +from .multi_loss_factory import AELoss, HeatmapLoss, MultiLossFactory +from .regression_loss import (BoneLoss, L1Loss, MPJPELoss, MSELoss, + SemiSupervisionLoss, SmoothL1Loss, SoftWingLoss, + WingLoss) + +__all__ = [ + 'JointsMSELoss', 'JointsOHKMMSELoss', 'HeatmapLoss', 'AELoss', + 'MultiLossFactory', 'MeshLoss', 'GANLoss', 'SmoothL1Loss', 'WingLoss', + 'MPJPELoss', 'MSELoss', 'L1Loss', 'BCELoss', 'BoneLoss', + 'SemiSupervisionLoss', 'SoftWingLoss', 'AdaptiveWingLoss' +] diff --git a/easy_ViTPose/vit_models/losses/classfication_loss.py b/easy_ViTPose/vit_models/losses/classfication_loss.py new file mode 100644 index 0000000000000000000000000000000000000000..34a46d5efc2652141c476427f0b7849d1d2eb263 --- /dev/null +++ b/easy_ViTPose/vit_models/losses/classfication_loss.py @@ -0,0 +1,41 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import torch.nn as nn +import torch.nn.functional as F + + +__all__ = ['BCELoss'] + + +class BCELoss(nn.Module): + """Binary Cross Entropy loss.""" + + def __init__(self, use_target_weight=False, loss_weight=1.): + super().__init__() + self.criterion = F.binary_cross_entropy + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + - batch_size: N + - num_labels: K + + Args: + output (torch.Tensor[N, K]): Output classification. + target (torch.Tensor[N, K]): Target classification. + target_weight (torch.Tensor[N, K] or torch.Tensor[N]): + Weights across different labels. + """ + + if self.use_target_weight: + assert target_weight is not None + loss = self.criterion(output, target, reduction='none') + if target_weight.dim() == 1: + target_weight = target_weight[:, None] + loss = (loss * target_weight).mean() + else: + loss = self.criterion(output, target) + + return loss * self.loss_weight diff --git a/easy_ViTPose/vit_models/losses/heatmap_loss.py b/easy_ViTPose/vit_models/losses/heatmap_loss.py new file mode 100644 index 0000000000000000000000000000000000000000..c3c36f86a7d255e4f251e38530242d3c29c38412 --- /dev/null +++ b/easy_ViTPose/vit_models/losses/heatmap_loss.py @@ -0,0 +1,83 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import torch +import torch.nn as nn + + +class AdaptiveWingLoss(nn.Module): + """Adaptive wing loss. paper ref: 'Adaptive Wing Loss for Robust Face + Alignment via Heatmap Regression' Wang et al. ICCV'2019. + + Args: + alpha (float), omega (float), epsilon (float), theta (float) + are hyper-parameters. + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, + alpha=2.1, + omega=14, + epsilon=1, + theta=0.5, + use_target_weight=False, + loss_weight=1.): + super().__init__() + self.alpha = float(alpha) + self.omega = float(omega) + self.epsilon = float(epsilon) + self.theta = float(theta) + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def criterion(self, pred, target): + """Criterion of wingloss. + + Note: + batch_size: N + num_keypoints: K + + Args: + pred (torch.Tensor[NxKxHxW]): Predicted heatmaps. + target (torch.Tensor[NxKxHxW]): Target heatmaps. + """ + H, W = pred.shape[2:4] + delta = (target - pred).abs() + + A = self.omega * ( + 1 / (1 + torch.pow(self.theta / self.epsilon, self.alpha - target)) + ) * (self.alpha - target) * (torch.pow( + self.theta / self.epsilon, + self.alpha - target - 1)) * (1 / self.epsilon) + C = self.theta * A - self.omega * torch.log( + 1 + torch.pow(self.theta / self.epsilon, self.alpha - target)) + + losses = torch.where( + delta < self.theta, + self.omega * + torch.log(1 + + torch.pow(delta / self.epsilon, self.alpha - target)), + A * delta - C) + + return torch.mean(losses) + + def forward(self, output, target, target_weight): + """Forward function. + + Note: + batch_size: N + num_keypoints: K + + Args: + output (torch.Tensor[NxKxHxW]): Output heatmaps. + target (torch.Tensor[NxKxHxW]): Target heatmaps. + target_weight (torch.Tensor[NxKx1]): + Weights across different joint types. + """ + if self.use_target_weight: + loss = self.criterion(output * target_weight.unsqueeze(-1), + target * target_weight.unsqueeze(-1)) + else: + loss = self.criterion(output, target) + + return loss * self.loss_weight diff --git a/easy_ViTPose/vit_models/losses/mesh_loss.py b/easy_ViTPose/vit_models/losses/mesh_loss.py new file mode 100644 index 0000000000000000000000000000000000000000..defbf5401ad778939bf5be84900a7562ae6f6748 --- /dev/null +++ b/easy_ViTPose/vit_models/losses/mesh_loss.py @@ -0,0 +1,402 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import torch +import torch.nn as nn + +__all__ = ['MeshLoss', 'GANLoss'] + +def rot6d_to_rotmat(x): + """Convert 6D rotation representation to 3x3 rotation matrix. + + Based on Zhou et al., "On the Continuity of Rotation + Representations in Neural Networks", CVPR 2019 + Input: + (B,6) Batch of 6-D rotation representations + Output: + (B,3,3) Batch of corresponding rotation matrices + """ + x = x.view(-1, 3, 2) + a1 = x[:, :, 0] + a2 = x[:, :, 1] + b1 = F.normalize(a1) + b2 = F.normalize(a2 - torch.einsum('bi,bi->b', b1, a2).unsqueeze(-1) * b1) + b3 = torch.cross(b1, b2) + return torch.stack((b1, b2, b3), dim=-1) + + +def batch_rodrigues(theta): + """Convert axis-angle representation to rotation matrix. + Args: + theta: size = [B, 3] + Returns: + Rotation matrix corresponding to the quaternion + -- size = [B, 3, 3] + """ + l2norm = torch.norm(theta + 1e-8, p=2, dim=1) + angle = torch.unsqueeze(l2norm, -1) + normalized = torch.div(theta, angle) + angle = angle * 0.5 + v_cos = torch.cos(angle) + v_sin = torch.sin(angle) + quat = torch.cat([v_cos, v_sin * normalized], dim=1) + return quat_to_rotmat(quat) + + +def quat_to_rotmat(quat): + """Convert quaternion coefficients to rotation matrix. + Args: + quat: size = [B, 4] 4 <===>(w, x, y, z) + Returns: + Rotation matrix corresponding to the quaternion + -- size = [B, 3, 3] + """ + norm_quat = quat + norm_quat = norm_quat / norm_quat.norm(p=2, dim=1, keepdim=True) + w, x, y, z = norm_quat[:, 0], norm_quat[:, 1],\ + norm_quat[:, 2], norm_quat[:, 3] + + B = quat.size(0) + + w2, x2, y2, z2 = w.pow(2), x.pow(2), y.pow(2), z.pow(2) + wx, wy, wz = w * x, w * y, w * z + xy, xz, yz = x * y, x * z, y * z + + rotMat = torch.stack([ + w2 + x2 - y2 - z2, 2 * xy - 2 * wz, 2 * wy + 2 * xz, 2 * wz + 2 * xy, + w2 - x2 + y2 - z2, 2 * yz - 2 * wx, 2 * xz - 2 * wy, 2 * wx + 2 * yz, + w2 - x2 - y2 + z2 + ], + dim=1).view(B, 3, 3) + return rotMat + + + +def perspective_projection(points, rotation, translation, focal_length, + camera_center): + """This function computes the perspective projection of a set of 3D points. + + Note: + - batch size: B + - point number: N + + Args: + points (Tensor([B, N, 3])): A set of 3D points + rotation (Tensor([B, 3, 3])): Camera rotation matrix + translation (Tensor([B, 3])): Camera translation + focal_length (Tensor([B,])): Focal length + camera_center (Tensor([B, 2])): Camera center + + Returns: + projected_points (Tensor([B, N, 2])): Projected 2D + points in image space. + """ + + batch_size = points.shape[0] + K = torch.zeros([batch_size, 3, 3], device=points.device) + K[:, 0, 0] = focal_length + K[:, 1, 1] = focal_length + K[:, 2, 2] = 1. + K[:, :-1, -1] = camera_center + + # Transform points + points = torch.einsum('bij,bkj->bki', rotation, points) + points = points + translation.unsqueeze(1) + + # Apply perspective distortion + projected_points = points / points[:, :, -1].unsqueeze(-1) + + # Apply camera intrinsics + projected_points = torch.einsum('bij,bkj->bki', K, projected_points) + projected_points = projected_points[:, :, :-1] + return projected_points + + +class MeshLoss(nn.Module): + """Mix loss for 3D human mesh. It is composed of loss on 2D joints, 3D + joints, mesh vertices and smpl parameters (if any). + + Args: + joints_2d_loss_weight (float): Weight for loss on 2D joints. + joints_3d_loss_weight (float): Weight for loss on 3D joints. + vertex_loss_weight (float): Weight for loss on 3D verteices. + smpl_pose_loss_weight (float): Weight for loss on SMPL + pose parameters. + smpl_beta_loss_weight (float): Weight for loss on SMPL + shape parameters. + img_res (int): Input image resolution. + focal_length (float): Focal length of camera model. Default=5000. + """ + + def __init__(self, + joints_2d_loss_weight, + joints_3d_loss_weight, + vertex_loss_weight, + smpl_pose_loss_weight, + smpl_beta_loss_weight, + img_res, + focal_length=5000): + + super().__init__() + # Per-vertex loss on the mesh + self.criterion_vertex = nn.L1Loss(reduction='none') + + # Joints (2D and 3D) loss + self.criterion_joints_2d = nn.SmoothL1Loss(reduction='none') + self.criterion_joints_3d = nn.SmoothL1Loss(reduction='none') + + # Loss for SMPL parameter regression + self.criterion_regr = nn.MSELoss(reduction='none') + + self.joints_2d_loss_weight = joints_2d_loss_weight + self.joints_3d_loss_weight = joints_3d_loss_weight + self.vertex_loss_weight = vertex_loss_weight + self.smpl_pose_loss_weight = smpl_pose_loss_weight + self.smpl_beta_loss_weight = smpl_beta_loss_weight + self.focal_length = focal_length + self.img_res = img_res + + def joints_2d_loss(self, pred_joints_2d, gt_joints_2d, joints_2d_visible): + """Compute 2D reprojection loss on the joints. + + The loss is weighted by joints_2d_visible. + """ + conf = joints_2d_visible.float() + loss = (conf * + self.criterion_joints_2d(pred_joints_2d, gt_joints_2d)).mean() + return loss + + def joints_3d_loss(self, pred_joints_3d, gt_joints_3d, joints_3d_visible): + """Compute 3D joints loss for the examples that 3D joint annotations + are available. + + The loss is weighted by joints_3d_visible. + """ + conf = joints_3d_visible.float() + if len(gt_joints_3d) > 0: + gt_pelvis = (gt_joints_3d[:, 2, :] + gt_joints_3d[:, 3, :]) / 2 + gt_joints_3d = gt_joints_3d - gt_pelvis[:, None, :] + pred_pelvis = (pred_joints_3d[:, 2, :] + + pred_joints_3d[:, 3, :]) / 2 + pred_joints_3d = pred_joints_3d - pred_pelvis[:, None, :] + return ( + conf * + self.criterion_joints_3d(pred_joints_3d, gt_joints_3d)).mean() + return pred_joints_3d.sum() * 0 + + def vertex_loss(self, pred_vertices, gt_vertices, has_smpl): + """Compute 3D vertex loss for the examples that 3D human mesh + annotations are available. + + The loss is weighted by the has_smpl. + """ + conf = has_smpl.float() + loss_vertex = self.criterion_vertex(pred_vertices, gt_vertices) + loss_vertex = (conf[:, None, None] * loss_vertex).mean() + return loss_vertex + + def smpl_losses(self, pred_rotmat, pred_betas, gt_pose, gt_betas, + has_smpl): + """Compute SMPL parameters loss for the examples that SMPL parameter + annotations are available. + + The loss is weighted by has_smpl. + """ + conf = has_smpl.float() + gt_rotmat = batch_rodrigues(gt_pose.view(-1, 3)).view(-1, 24, 3, 3) + loss_regr_pose = self.criterion_regr(pred_rotmat, gt_rotmat) + loss_regr_betas = self.criterion_regr(pred_betas, gt_betas) + loss_regr_pose = (conf[:, None, None, None] * loss_regr_pose).mean() + loss_regr_betas = (conf[:, None] * loss_regr_betas).mean() + return loss_regr_pose, loss_regr_betas + + def project_points(self, points_3d, camera): + """Perform orthographic projection of 3D points using the camera + parameters, return projected 2D points in image plane. + + Note: + - batch size: B + - point number: N + + Args: + points_3d (Tensor([B, N, 3])): 3D points. + camera (Tensor([B, 3])): camera parameters with the + 3 channel as (scale, translation_x, translation_y) + + Returns: + Tensor([B, N, 2]): projected 2D points \ + in image space. + """ + batch_size = points_3d.shape[0] + device = points_3d.device + cam_t = torch.stack([ + camera[:, 1], camera[:, 2], 2 * self.focal_length / + (self.img_res * camera[:, 0] + 1e-9) + ], + dim=-1) + camera_center = camera.new_zeros([batch_size, 2]) + rot_t = torch.eye( + 3, device=device, + dtype=points_3d.dtype).unsqueeze(0).expand(batch_size, -1, -1) + joints_2d = perspective_projection( + points_3d, + rotation=rot_t, + translation=cam_t, + focal_length=self.focal_length, + camera_center=camera_center) + return joints_2d + + def forward(self, output, target): + """Forward function. + + Args: + output (dict): dict of network predicted results. + Keys: 'vertices', 'joints_3d', 'camera', + 'pose'(optional), 'beta'(optional) + target (dict): dict of ground-truth labels. + Keys: 'vertices', 'joints_3d', 'joints_3d_visible', + 'joints_2d', 'joints_2d_visible', 'pose', 'beta', + 'has_smpl' + + Returns: + dict: dict of losses. + """ + losses = {} + + # Per-vertex loss for the shape + pred_vertices = output['vertices'] + + gt_vertices = target['vertices'] + has_smpl = target['has_smpl'] + loss_vertex = self.vertex_loss(pred_vertices, gt_vertices, has_smpl) + losses['vertex_loss'] = loss_vertex * self.vertex_loss_weight + + # Compute loss on SMPL parameters, if available + if 'pose' in output.keys() and 'beta' in output.keys(): + pred_rotmat = output['pose'] + pred_betas = output['beta'] + gt_pose = target['pose'] + gt_betas = target['beta'] + loss_regr_pose, loss_regr_betas = self.smpl_losses( + pred_rotmat, pred_betas, gt_pose, gt_betas, has_smpl) + losses['smpl_pose_loss'] = \ + loss_regr_pose * self.smpl_pose_loss_weight + losses['smpl_beta_loss'] = \ + loss_regr_betas * self.smpl_beta_loss_weight + + # Compute 3D joints loss + pred_joints_3d = output['joints_3d'] + gt_joints_3d = target['joints_3d'] + joints_3d_visible = target['joints_3d_visible'] + loss_joints_3d = self.joints_3d_loss(pred_joints_3d, gt_joints_3d, + joints_3d_visible) + losses['joints_3d_loss'] = loss_joints_3d * self.joints_3d_loss_weight + + # Compute 2D reprojection loss for the 2D joints + pred_camera = output['camera'] + gt_joints_2d = target['joints_2d'] + joints_2d_visible = target['joints_2d_visible'] + pred_joints_2d = self.project_points(pred_joints_3d, pred_camera) + + # Normalize keypoints to [-1,1] + # The coordinate origin of pred_joints_2d is + # the center of the input image. + pred_joints_2d = 2 * pred_joints_2d / (self.img_res - 1) + # The coordinate origin of gt_joints_2d is + # the top left corner of the input image. + gt_joints_2d = 2 * gt_joints_2d / (self.img_res - 1) - 1 + loss_joints_2d = self.joints_2d_loss(pred_joints_2d, gt_joints_2d, + joints_2d_visible) + losses['joints_2d_loss'] = loss_joints_2d * self.joints_2d_loss_weight + + return losses + + +class GANLoss(nn.Module): + """Define GAN loss. + + Args: + gan_type (str): Support 'vanilla', 'lsgan', 'wgan', 'hinge'. + real_label_val (float): The value for real label. Default: 1.0. + fake_label_val (float): The value for fake label. Default: 0.0. + loss_weight (float): Loss weight. Default: 1.0. + Note that loss_weight is only for generators; and it is always 1.0 + for discriminators. + """ + + def __init__(self, + gan_type, + real_label_val=1.0, + fake_label_val=0.0, + loss_weight=1.0): + super().__init__() + self.gan_type = gan_type + self.loss_weight = loss_weight + self.real_label_val = real_label_val + self.fake_label_val = fake_label_val + + if self.gan_type == 'vanilla': + self.loss = nn.BCEWithLogitsLoss() + elif self.gan_type == 'lsgan': + self.loss = nn.MSELoss() + elif self.gan_type == 'wgan': + self.loss = self._wgan_loss + elif self.gan_type == 'hinge': + self.loss = nn.ReLU() + else: + raise NotImplementedError( + f'GAN type {self.gan_type} is not implemented.') + + @staticmethod + def _wgan_loss(input, target): + """wgan loss. + + Args: + input (Tensor): Input tensor. + target (bool): Target label. + + Returns: + Tensor: wgan loss. + """ + return -input.mean() if target else input.mean() + + def get_target_label(self, input, target_is_real): + """Get target label. + + Args: + input (Tensor): Input tensor. + target_is_real (bool): Whether the target is real or fake. + + Returns: + (bool | Tensor): Target tensor. Return bool for wgan, \ + otherwise, return Tensor. + """ + + if self.gan_type == 'wgan': + return target_is_real + target_val = ( + self.real_label_val if target_is_real else self.fake_label_val) + return input.new_ones(input.size()) * target_val + + def forward(self, input, target_is_real, is_disc=False): + """ + Args: + input (Tensor): The input for the loss module, i.e., the network + prediction. + target_is_real (bool): Whether the targe is real or fake. + is_disc (bool): Whether the loss for discriminators or not. + Default: False. + + Returns: + Tensor: GAN loss value. + """ + target_label = self.get_target_label(input, target_is_real) + if self.gan_type == 'hinge': + if is_disc: # for discriminators in hinge-gan + input = -input if target_is_real else input + loss = self.loss(1 + input).mean() + else: # for generators in hinge-gan + loss = -input.mean() + else: # other gan types + loss = self.loss(input, target_label) + + # loss_weight is always 1.0 for discriminators + return loss if is_disc else loss * self.loss_weight diff --git a/easy_ViTPose/vit_models/losses/mse_loss.py b/easy_ViTPose/vit_models/losses/mse_loss.py new file mode 100644 index 0000000000000000000000000000000000000000..ec649b809a38e02ab8f0b7fc22c8072669f97ae0 --- /dev/null +++ b/easy_ViTPose/vit_models/losses/mse_loss.py @@ -0,0 +1,151 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import torch +import torch.nn as nn + + +__all__ = ['JointsMSELoss', 'JointsOHKMMSELoss',] + + +class JointsMSELoss(nn.Module): + """MSE loss for heatmaps. + + Args: + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, use_target_weight=False, loss_weight=1.): + super().__init__() + self.criterion = nn.MSELoss() + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def forward(self, output, target, target_weight): + """Forward function.""" + batch_size = output.size(0) + num_joints = output.size(1) + + heatmaps_pred = output.reshape( + (batch_size, num_joints, -1)).split(1, 1) + heatmaps_gt = target.reshape((batch_size, num_joints, -1)).split(1, 1) + + loss = 0. + + for idx in range(num_joints): + heatmap_pred = heatmaps_pred[idx].squeeze(1) + heatmap_gt = heatmaps_gt[idx].squeeze(1) + if self.use_target_weight: + loss += self.criterion(heatmap_pred * target_weight[:, idx], + heatmap_gt * target_weight[:, idx]) + else: + loss += self.criterion(heatmap_pred, heatmap_gt) + + return loss / num_joints * self.loss_weight + + +class CombinedTargetMSELoss(nn.Module): + """MSE loss for combined target. + CombinedTarget: The combination of classification target + (response map) and regression target (offset map). + Paper ref: Huang et al. The Devil is in the Details: Delving into + Unbiased Data Processing for Human Pose Estimation (CVPR 2020). + + Args: + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, use_target_weight, loss_weight=1.): + super().__init__() + self.criterion = nn.MSELoss(reduction='mean') + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def forward(self, output, target, target_weight): + batch_size = output.size(0) + num_channels = output.size(1) + heatmaps_pred = output.reshape( + (batch_size, num_channels, -1)).split(1, 1) + heatmaps_gt = target.reshape( + (batch_size, num_channels, -1)).split(1, 1) + loss = 0. + num_joints = num_channels // 3 + for idx in range(num_joints): + heatmap_pred = heatmaps_pred[idx * 3].squeeze() + heatmap_gt = heatmaps_gt[idx * 3].squeeze() + offset_x_pred = heatmaps_pred[idx * 3 + 1].squeeze() + offset_x_gt = heatmaps_gt[idx * 3 + 1].squeeze() + offset_y_pred = heatmaps_pred[idx * 3 + 2].squeeze() + offset_y_gt = heatmaps_gt[idx * 3 + 2].squeeze() + if self.use_target_weight: + heatmap_pred = heatmap_pred * target_weight[:, idx] + heatmap_gt = heatmap_gt * target_weight[:, idx] + # classification loss + loss += 0.5 * self.criterion(heatmap_pred, heatmap_gt) + # regression loss + loss += 0.5 * self.criterion(heatmap_gt * offset_x_pred, + heatmap_gt * offset_x_gt) + loss += 0.5 * self.criterion(heatmap_gt * offset_y_pred, + heatmap_gt * offset_y_gt) + return loss / num_joints * self.loss_weight + + +class JointsOHKMMSELoss(nn.Module): + """MSE loss with online hard keypoint mining. + + Args: + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + topk (int): Only top k joint losses are kept. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, use_target_weight=False, topk=8, loss_weight=1.): + super().__init__() + assert topk > 0 + self.criterion = nn.MSELoss(reduction='none') + self.use_target_weight = use_target_weight + self.topk = topk + self.loss_weight = loss_weight + + def _ohkm(self, loss): + """Online hard keypoint mining.""" + ohkm_loss = 0. + N = len(loss) + for i in range(N): + sub_loss = loss[i] + _, topk_idx = torch.topk( + sub_loss, k=self.topk, dim=0, sorted=False) + tmp_loss = torch.gather(sub_loss, 0, topk_idx) + ohkm_loss += torch.sum(tmp_loss) / self.topk + ohkm_loss /= N + return ohkm_loss + + def forward(self, output, target, target_weight): + """Forward function.""" + batch_size = output.size(0) + num_joints = output.size(1) + if num_joints < self.topk: + raise ValueError(f'topk ({self.topk}) should not ' + f'larger than num_joints ({num_joints}).') + heatmaps_pred = output.reshape( + (batch_size, num_joints, -1)).split(1, 1) + heatmaps_gt = target.reshape((batch_size, num_joints, -1)).split(1, 1) + + losses = [] + for idx in range(num_joints): + heatmap_pred = heatmaps_pred[idx].squeeze(1) + heatmap_gt = heatmaps_gt[idx].squeeze(1) + if self.use_target_weight: + losses.append( + self.criterion(heatmap_pred * target_weight[:, idx], + heatmap_gt * target_weight[:, idx])) + else: + losses.append(self.criterion(heatmap_pred, heatmap_gt)) + + losses = [loss.mean(dim=1).unsqueeze(dim=1) for loss in losses] + losses = torch.cat(losses, dim=1) + + return self._ohkm(losses) * self.loss_weight diff --git a/easy_ViTPose/vit_models/losses/multi_loss_factory.py b/easy_ViTPose/vit_models/losses/multi_loss_factory.py new file mode 100644 index 0000000000000000000000000000000000000000..890652b58bef7e8ef5a7abe356d23b130bb829df --- /dev/null +++ b/easy_ViTPose/vit_models/losses/multi_loss_factory.py @@ -0,0 +1,279 @@ +# ------------------------------------------------------------------------------ +# Adapted from https://github.com/HRNet/HigherHRNet-Human-Pose-Estimation +# Original licence: Copyright (c) Microsoft, under the MIT License. +# ------------------------------------------------------------------------------ + +import torch +import torch.nn as nn + + +__all__ = ['HeatmapLoss', 'AELoss', 'MultiLossFactory'] + + +def _make_input(t, requires_grad=False, device=torch.device('cpu')): + """Make zero inputs for AE loss. + + Args: + t (torch.Tensor): input + requires_grad (bool): Option to use requires_grad. + device: torch device + + Returns: + torch.Tensor: zero input. + """ + inp = torch.autograd.Variable(t, requires_grad=requires_grad) + inp = inp.sum() + inp = inp.to(device) + return inp + + +class HeatmapLoss(nn.Module): + """Accumulate the heatmap loss for each image in the batch. + + Args: + supervise_empty (bool): Whether to supervise empty channels. + """ + + def __init__(self, supervise_empty=True): + super().__init__() + self.supervise_empty = supervise_empty + + def forward(self, pred, gt, mask): + """Forward function. + + Note: + - batch_size: N + - heatmaps weight: W + - heatmaps height: H + - max_num_people: M + - num_keypoints: K + + Args: + pred (torch.Tensor[N,K,H,W]):heatmap of output. + gt (torch.Tensor[N,K,H,W]): target heatmap. + mask (torch.Tensor[N,H,W]): mask of target. + """ + assert pred.size() == gt.size( + ), f'pred.size() is {pred.size()}, gt.size() is {gt.size()}' + + if not self.supervise_empty: + empty_mask = (gt.sum(dim=[2, 3], keepdim=True) > 0).float() + loss = ((pred - gt)**2) * empty_mask.expand_as( + pred) * mask[:, None, :, :].expand_as(pred) + else: + loss = ((pred - gt)**2) * mask[:, None, :, :].expand_as(pred) + loss = loss.mean(dim=3).mean(dim=2).mean(dim=1) + return loss + + +class AELoss(nn.Module): + """Associative Embedding loss. + + `Associative Embedding: End-to-End Learning for Joint Detection and + Grouping `_. + """ + + def __init__(self, loss_type): + super().__init__() + self.loss_type = loss_type + + def singleTagLoss(self, pred_tag, joints): + """Associative embedding loss for one image. + + Note: + - heatmaps weight: W + - heatmaps height: H + - max_num_people: M + - num_keypoints: K + + Args: + pred_tag (torch.Tensor[KxHxW,1]): tag of output for one image. + joints (torch.Tensor[M,K,2]): joints information for one image. + """ + tags = [] + pull = 0 + for joints_per_person in joints: + tmp = [] + for joint in joints_per_person: + if joint[1] > 0: + tmp.append(pred_tag[joint[0]]) + if len(tmp) == 0: + continue + tmp = torch.stack(tmp) + tags.append(torch.mean(tmp, dim=0)) + pull = pull + torch.mean((tmp - tags[-1].expand_as(tmp))**2) + + num_tags = len(tags) + if num_tags == 0: + return ( + _make_input(torch.zeros(1).float(), device=pred_tag.device), + _make_input(torch.zeros(1).float(), device=pred_tag.device)) + elif num_tags == 1: + return (_make_input( + torch.zeros(1).float(), device=pred_tag.device), pull) + + tags = torch.stack(tags) + + size = (num_tags, num_tags) + A = tags.expand(*size) + B = A.permute(1, 0) + + diff = A - B + + if self.loss_type == 'exp': + diff = torch.pow(diff, 2) + push = torch.exp(-diff) + push = torch.sum(push) - num_tags + elif self.loss_type == 'max': + diff = 1 - torch.abs(diff) + push = torch.clamp(diff, min=0).sum() - num_tags + else: + raise ValueError('Unknown ae loss type') + + push_loss = push / ((num_tags - 1) * num_tags) * 0.5 + pull_loss = pull / (num_tags) + + return push_loss, pull_loss + + def forward(self, tags, joints): + """Accumulate the tag loss for each image in the batch. + + Note: + - batch_size: N + - heatmaps weight: W + - heatmaps height: H + - max_num_people: M + - num_keypoints: K + + Args: + tags (torch.Tensor[N,KxHxW,1]): tag channels of output. + joints (torch.Tensor[N,M,K,2]): joints information. + """ + pushes, pulls = [], [] + joints = joints.cpu().data.numpy() + batch_size = tags.size(0) + for i in range(batch_size): + push, pull = self.singleTagLoss(tags[i], joints[i]) + pushes.append(push) + pulls.append(pull) + return torch.stack(pushes), torch.stack(pulls) + + +class MultiLossFactory(nn.Module): + """Loss for bottom-up models. + + Args: + num_joints (int): Number of keypoints. + num_stages (int): Number of stages. + ae_loss_type (str): Type of ae loss. + with_ae_loss (list[bool]): Use ae loss or not in multi-heatmap. + push_loss_factor (list[float]): + Parameter of push loss in multi-heatmap. + pull_loss_factor (list[float]): + Parameter of pull loss in multi-heatmap. + with_heatmap_loss (list[bool]): + Use heatmap loss or not in multi-heatmap. + heatmaps_loss_factor (list[float]): + Parameter of heatmap loss in multi-heatmap. + supervise_empty (bool): Whether to supervise empty channels. + """ + + def __init__(self, + num_joints, + num_stages, + ae_loss_type, + with_ae_loss, + push_loss_factor, + pull_loss_factor, + with_heatmaps_loss, + heatmaps_loss_factor, + supervise_empty=True): + super().__init__() + + assert isinstance(with_heatmaps_loss, (list, tuple)), \ + 'with_heatmaps_loss should be a list or tuple' + assert isinstance(heatmaps_loss_factor, (list, tuple)), \ + 'heatmaps_loss_factor should be a list or tuple' + assert isinstance(with_ae_loss, (list, tuple)), \ + 'with_ae_loss should be a list or tuple' + assert isinstance(push_loss_factor, (list, tuple)), \ + 'push_loss_factor should be a list or tuple' + assert isinstance(pull_loss_factor, (list, tuple)), \ + 'pull_loss_factor should be a list or tuple' + + self.num_joints = num_joints + self.num_stages = num_stages + self.ae_loss_type = ae_loss_type + self.with_ae_loss = with_ae_loss + self.push_loss_factor = push_loss_factor + self.pull_loss_factor = pull_loss_factor + self.with_heatmaps_loss = with_heatmaps_loss + self.heatmaps_loss_factor = heatmaps_loss_factor + + self.heatmaps_loss = \ + nn.ModuleList( + [ + HeatmapLoss(supervise_empty) + if with_heatmaps_loss else None + for with_heatmaps_loss in self.with_heatmaps_loss + ] + ) + + self.ae_loss = \ + nn.ModuleList( + [ + AELoss(self.ae_loss_type) if with_ae_loss else None + for with_ae_loss in self.with_ae_loss + ] + ) + + def forward(self, outputs, heatmaps, masks, joints): + """Forward function to calculate losses. + + Note: + - batch_size: N + - heatmaps weight: W + - heatmaps height: H + - max_num_people: M + - num_keypoints: K + - output_channel: C C=2K if use ae loss else K + + Args: + outputs (list(torch.Tensor[N,C,H,W])): outputs of stages. + heatmaps (list(torch.Tensor[N,K,H,W])): target of heatmaps. + masks (list(torch.Tensor[N,H,W])): masks of heatmaps. + joints (list(torch.Tensor[N,M,K,2])): joints of ae loss. + """ + heatmaps_losses = [] + push_losses = [] + pull_losses = [] + for idx in range(len(outputs)): + offset_feat = 0 + if self.heatmaps_loss[idx]: + heatmaps_pred = outputs[idx][:, :self.num_joints] + offset_feat = self.num_joints + heatmaps_loss = self.heatmaps_loss[idx](heatmaps_pred, + heatmaps[idx], + masks[idx]) + heatmaps_loss = heatmaps_loss * self.heatmaps_loss_factor[idx] + heatmaps_losses.append(heatmaps_loss) + else: + heatmaps_losses.append(None) + + if self.ae_loss[idx]: + tags_pred = outputs[idx][:, offset_feat:] + batch_size = tags_pred.size()[0] + tags_pred = tags_pred.contiguous().view(batch_size, -1, 1) + + push_loss, pull_loss = self.ae_loss[idx](tags_pred, + joints[idx]) + push_loss = push_loss * self.push_loss_factor[idx] + pull_loss = pull_loss * self.pull_loss_factor[idx] + + push_losses.append(push_loss) + pull_losses.append(pull_loss) + else: + push_losses.append(None) + pull_losses.append(None) + + return heatmaps_losses, push_losses, pull_losses diff --git a/easy_ViTPose/vit_models/losses/regression_loss.py b/easy_ViTPose/vit_models/losses/regression_loss.py new file mode 100644 index 0000000000000000000000000000000000000000..97cddd65c748a224e8edb877ad2f9778a7a241e3 --- /dev/null +++ b/easy_ViTPose/vit_models/losses/regression_loss.py @@ -0,0 +1,444 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import math + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +__all__ = ['SmoothL1Loss', 'SoftWingLoss', 'SoftWingLoss', + 'L1Loss', 'MPJPELoss', 'MSELoss', 'BoneLoss', + 'SemiSupervisionLoss'] + + +class SmoothL1Loss(nn.Module): + """SmoothL1Loss loss. + + Args: + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, use_target_weight=False, loss_weight=1.): + super().__init__() + self.criterion = F.smooth_l1_loss + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + - batch_size: N + - num_keypoints: K + - dimension of keypoints: D (D=2 or D=3) + + Args: + output (torch.Tensor[N, K, D]): Output regression. + target (torch.Tensor[N, K, D]): Target regression. + target_weight (torch.Tensor[N, K, D]): + Weights across different joint types. + """ + if self.use_target_weight: + assert target_weight is not None + loss = self.criterion(output * target_weight, + target * target_weight) + else: + loss = self.criterion(output, target) + + return loss * self.loss_weight + + +class WingLoss(nn.Module): + """Wing Loss. paper ref: 'Wing Loss for Robust Facial Landmark Localisation + with Convolutional Neural Networks' Feng et al. CVPR'2018. + + Args: + omega (float): Also referred to as width. + epsilon (float): Also referred to as curvature. + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, + omega=10.0, + epsilon=2.0, + use_target_weight=False, + loss_weight=1.): + super().__init__() + self.omega = omega + self.epsilon = epsilon + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + # constant that smoothly links the piecewise-defined linear + # and nonlinear parts + self.C = self.omega * (1.0 - math.log(1.0 + self.omega / self.epsilon)) + + def criterion(self, pred, target): + """Criterion of wingloss. + + Note: + - batch_size: N + - num_keypoints: K + - dimension of keypoints: D (D=2 or D=3) + + Args: + pred (torch.Tensor[N, K, D]): Output regression. + target (torch.Tensor[N, K, D]): Target regression. + """ + delta = (target - pred).abs() + losses = torch.where( + delta < self.omega, + self.omega * torch.log(1.0 + delta / self.epsilon), delta - self.C) + return torch.mean(torch.sum(losses, dim=[1, 2]), dim=0) + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + - batch_size: N + - num_keypoints: K + - dimension of keypoints: D (D=2 or D=3) + + Args: + output (torch.Tensor[N, K, D]): Output regression. + target (torch.Tensor[N, K, D]): Target regression. + target_weight (torch.Tensor[N,K,D]): + Weights across different joint types. + """ + if self.use_target_weight: + assert target_weight is not None + loss = self.criterion(output * target_weight, + target * target_weight) + else: + loss = self.criterion(output, target) + + return loss * self.loss_weight + + + +class SoftWingLoss(nn.Module): + """Soft Wing Loss 'Structure-Coherent Deep Feature Learning for Robust Face + Alignment' Lin et al. TIP'2021. + + loss = + 1. |x| , if |x| < omega1 + 2. omega2*ln(1+|x|/epsilon) + B, if |x| >= omega1 + + Args: + omega1 (float): The first threshold. + omega2 (float): The second threshold. + epsilon (float): Also referred to as curvature. + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, + omega1=2.0, + omega2=20.0, + epsilon=0.5, + use_target_weight=False, + loss_weight=1.): + super().__init__() + self.omega1 = omega1 + self.omega2 = omega2 + self.epsilon = epsilon + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + # constant that smoothly links the piecewise-defined linear + # and nonlinear parts + self.B = self.omega1 - self.omega2 * math.log(1.0 + self.omega1 / + self.epsilon) + + def criterion(self, pred, target): + """Criterion of wingloss. + + Note: + batch_size: N + num_keypoints: K + dimension of keypoints: D (D=2 or D=3) + + Args: + pred (torch.Tensor[N, K, D]): Output regression. + target (torch.Tensor[N, K, D]): Target regression. + """ + delta = (target - pred).abs() + losses = torch.where( + delta < self.omega1, delta, + self.omega2 * torch.log(1.0 + delta / self.epsilon) + self.B) + return torch.mean(torch.sum(losses, dim=[1, 2]), dim=0) + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + batch_size: N + num_keypoints: K + dimension of keypoints: D (D=2 or D=3) + + Args: + output (torch.Tensor[N, K, D]): Output regression. + target (torch.Tensor[N, K, D]): Target regression. + target_weight (torch.Tensor[N, K, D]): + Weights across different joint types. + """ + if self.use_target_weight: + assert target_weight is not None + loss = self.criterion(output * target_weight, + target * target_weight) + else: + loss = self.criterion(output, target) + + return loss * self.loss_weight + + +class MPJPELoss(nn.Module): + """MPJPE (Mean Per Joint Position Error) loss. + + Args: + use_target_weight (bool): Option to use weighted MSE loss. + Different joint types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, use_target_weight=False, loss_weight=1.): + super().__init__() + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + - batch_size: N + - num_keypoints: K + - dimension of keypoints: D (D=2 or D=3) + + Args: + output (torch.Tensor[N, K, D]): Output regression. + target (torch.Tensor[N, K, D]): Target regression. + target_weight (torch.Tensor[N,K,D]): + Weights across different joint types. + """ + + if self.use_target_weight: + assert target_weight is not None + loss = torch.mean( + torch.norm((output - target) * target_weight, dim=-1)) + else: + loss = torch.mean(torch.norm(output - target, dim=-1)) + + return loss * self.loss_weight + + +class L1Loss(nn.Module): + """L1Loss loss .""" + + def __init__(self, use_target_weight=False, loss_weight=1.): + super().__init__() + self.criterion = F.l1_loss + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + - batch_size: N + - num_keypoints: K + + Args: + output (torch.Tensor[N, K, 2]): Output regression. + target (torch.Tensor[N, K, 2]): Target regression. + target_weight (torch.Tensor[N, K, 2]): + Weights across different joint types. + """ + if self.use_target_weight: + assert target_weight is not None + loss = self.criterion(output * target_weight, + target * target_weight) + else: + loss = self.criterion(output, target) + + return loss * self.loss_weight + + +class MSELoss(nn.Module): + """MSE loss for coordinate regression.""" + + def __init__(self, use_target_weight=False, loss_weight=1.): + super().__init__() + self.criterion = F.mse_loss + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + - batch_size: N + - num_keypoints: K + + Args: + output (torch.Tensor[N, K, 2]): Output regression. + target (torch.Tensor[N, K, 2]): Target regression. + target_weight (torch.Tensor[N, K, 2]): + Weights across different joint types. + """ + if self.use_target_weight: + assert target_weight is not None + loss = self.criterion(output * target_weight, + target * target_weight) + else: + loss = self.criterion(output, target) + + return loss * self.loss_weight + + +class BoneLoss(nn.Module): + """Bone length loss. + + Args: + joint_parents (list): Indices of each joint's parent joint. + use_target_weight (bool): Option to use weighted bone loss. + Different bone types may have different target weights. + loss_weight (float): Weight of the loss. Default: 1.0. + """ + + def __init__(self, joint_parents, use_target_weight=False, loss_weight=1.): + super().__init__() + self.joint_parents = joint_parents + self.use_target_weight = use_target_weight + self.loss_weight = loss_weight + + self.non_root_indices = [] + for i in range(len(self.joint_parents)): + if i != self.joint_parents[i]: + self.non_root_indices.append(i) + + def forward(self, output, target, target_weight=None): + """Forward function. + + Note: + - batch_size: N + - num_keypoints: K + - dimension of keypoints: D (D=2 or D=3) + + Args: + output (torch.Tensor[N, K, D]): Output regression. + target (torch.Tensor[N, K, D]): Target regression. + target_weight (torch.Tensor[N, K-1]): + Weights across different bone types. + """ + output_bone = torch.norm( + output - output[:, self.joint_parents, :], + dim=-1)[:, self.non_root_indices] + target_bone = torch.norm( + target - target[:, self.joint_parents, :], + dim=-1)[:, self.non_root_indices] + if self.use_target_weight: + assert target_weight is not None + loss = torch.mean( + torch.abs((output_bone * target_weight).mean(dim=0) - + (target_bone * target_weight).mean(dim=0))) + else: + loss = torch.mean( + torch.abs(output_bone.mean(dim=0) - target_bone.mean(dim=0))) + + return loss * self.loss_weight + + +class SemiSupervisionLoss(nn.Module): + """Semi-supervision loss for unlabeled data. It is composed of projection + loss and bone loss. + + Paper ref: `3D human pose estimation in video with temporal convolutions + and semi-supervised training` Dario Pavllo et al. CVPR'2019. + + Args: + joint_parents (list): Indices of each joint's parent joint. + projection_loss_weight (float): Weight for projection loss. + bone_loss_weight (float): Weight for bone loss. + warmup_iterations (int): Number of warmup iterations. In the first + `warmup_iterations` iterations, the model is trained only on + labeled data, and semi-supervision loss will be 0. + This is a workaround since currently we cannot access + epoch number in loss functions. Note that the iteration number in + an epoch can be changed due to different GPU numbers in multi-GPU + settings. So please set this parameter carefully. + warmup_iterations = dataset_size // samples_per_gpu // gpu_num + * warmup_epochs + """ + + def __init__(self, + joint_parents, + projection_loss_weight=1., + bone_loss_weight=1., + warmup_iterations=0): + super().__init__() + self.criterion_projection = MPJPELoss( + loss_weight=projection_loss_weight) + self.criterion_bone = BoneLoss( + joint_parents, loss_weight=bone_loss_weight) + self.warmup_iterations = warmup_iterations + self.num_iterations = 0 + + @staticmethod + def project_joints(x, intrinsics): + """Project 3D joint coordinates to 2D image plane using camera + intrinsic parameters. + + Args: + x (torch.Tensor[N, K, 3]): 3D joint coordinates. + intrinsics (torch.Tensor[N, 4] | torch.Tensor[N, 9]): Camera + intrinsics: f (2), c (2), k (3), p (2). + """ + while intrinsics.dim() < x.dim(): + intrinsics.unsqueeze_(1) + f = intrinsics[..., :2] + c = intrinsics[..., 2:4] + _x = torch.clamp(x[:, :, :2] / x[:, :, 2:], -1, 1) + if intrinsics.shape[-1] == 9: + k = intrinsics[..., 4:7] + p = intrinsics[..., 7:9] + + r2 = torch.sum(_x[:, :, :2]**2, dim=-1, keepdim=True) + radial = 1 + torch.sum( + k * torch.cat((r2, r2**2, r2**3), dim=-1), + dim=-1, + keepdim=True) + tan = torch.sum(p * _x, dim=-1, keepdim=True) + _x = _x * (radial + tan) + p * r2 + _x = f * _x + c + return _x + + def forward(self, output, target): + losses = dict() + + self.num_iterations += 1 + if self.num_iterations <= self.warmup_iterations: + return losses + + labeled_pose = output['labeled_pose'] + unlabeled_pose = output['unlabeled_pose'] + unlabeled_traj = output['unlabeled_traj'] + unlabeled_target_2d = target['unlabeled_target_2d'] + intrinsics = target['intrinsics'] + + # projection loss + unlabeled_output = unlabeled_pose + unlabeled_traj + unlabeled_output_2d = self.project_joints(unlabeled_output, intrinsics) + loss_proj = self.criterion_projection(unlabeled_output_2d, + unlabeled_target_2d, None) + losses['proj_loss'] = loss_proj + + # bone loss + loss_bone = self.criterion_bone(unlabeled_pose, labeled_pose, None) + losses['bone_loss'] = loss_bone + + return losses diff --git a/easy_ViTPose/vit_models/model.py b/easy_ViTPose/vit_models/model.py new file mode 100644 index 0000000000000000000000000000000000000000..dead3ea6b65ed30a964dd5907d4638f5e75b9c96 --- /dev/null +++ b/easy_ViTPose/vit_models/model.py @@ -0,0 +1,24 @@ +import torch.nn as nn + +from .backbone.vit import ViT +from .head.topdown_heatmap_simple_head import TopdownHeatmapSimpleHead + + +__all__ = ['ViTPose'] + + +class ViTPose(nn.Module): + def __init__(self, cfg: dict) -> None: + super(ViTPose, self).__init__() + + backbone_cfg = {k: v for k, v in cfg['backbone'].items() if k != 'type'} + head_cfg = {k: v for k, v in cfg['keypoint_head'].items() if k != 'type'} + + self.backbone = ViT(**backbone_cfg) + self.keypoint_head = TopdownHeatmapSimpleHead(**head_cfg) + + def forward_features(self, x): + return self.backbone(x) + + def forward(self, x): + return self.keypoint_head(self.backbone(x)) diff --git a/easy_ViTPose/vit_models/optimizer.py b/easy_ViTPose/vit_models/optimizer.py new file mode 100644 index 0000000000000000000000000000000000000000..2f93d84de1e3dc80185f43edcdb6df50f62a0ca3 --- /dev/null +++ b/easy_ViTPose/vit_models/optimizer.py @@ -0,0 +1,15 @@ +import torch.optim as optim + +class LayerDecayOptimizer: + def __init__(self, optimizer, layerwise_decay_rate): + self.optimizer = optimizer + self.layerwise_decay_rate = layerwise_decay_rate + self.param_groups = optimizer.param_groups + + def step(self, *args, **kwargs): + for i, group in enumerate(self.optimizer.param_groups): + group['lr'] *= self.layerwise_decay_rate[i] + self.optimizer.step(*args, **kwargs) + + def zero_grad(self, *args, **kwargs): + self.optimizer.zero_grad(*args, **kwargs) \ No newline at end of file diff --git a/easy_ViTPose/vit_utils/__init__.py b/easy_ViTPose/vit_utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..364e2e53a90ba05ea03d812b6e7a349f9ee6412e --- /dev/null +++ b/easy_ViTPose/vit_utils/__init__.py @@ -0,0 +1,6 @@ +from .util import * +from .top_down_eval import * +from .post_processing import * +from .visualization import * +from .dist_util import * +from .logging import * diff --git a/easy_ViTPose/vit_utils/dist_util.py b/easy_ViTPose/vit_utils/dist_util.py new file mode 100644 index 0000000000000000000000000000000000000000..087a3f20ce6949ac1fc3845ba91790494841658d --- /dev/null +++ b/easy_ViTPose/vit_utils/dist_util.py @@ -0,0 +1,212 @@ +# Copyright (c) OpenMMLab. All rights reserved. +# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved +import functools +import os +import socket +import subprocess +from collections import OrderedDict +from typing import Callable, List, Optional, Tuple + +import torch +import torch.multiprocessing as mp +from torch import distributed as dist +from torch._utils import (_flatten_dense_tensors, _take_tensors, + _unflatten_dense_tensors) + + +def is_mps_available() -> bool: + """Return True if mps devices exist. + + It's specialized for mac m1 chips and require torch version 1.12 or higher. + """ + try: + import torch + return hasattr(torch.backends, + 'mps') and torch.backends.mps.is_available() + except Exception: + return False + +def _find_free_port() -> str: + # Copied from https://github.com/facebookresearch/detectron2/blob/main/detectron2/engine/launch.py # noqa: E501 + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # Binding to port 0 will cause the OS to find an available port for us + sock.bind(('', 0)) + port = sock.getsockname()[1] + sock.close() + # NOTE: there is still a chance the port could be taken by other processes. + return port + + +def _is_free_port(port: int) -> bool: + ips = socket.gethostbyname_ex(socket.gethostname())[-1] + ips.append('localhost') + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + return all(s.connect_ex((ip, port)) != 0 for ip in ips) + + +def init_dist(launcher: str, backend: str = 'nccl', **kwargs) -> None: + if mp.get_start_method(allow_none=True) is None: + mp.set_start_method('spawn') + if launcher == 'pytorch': + _init_dist_pytorch(backend, **kwargs) + elif launcher == 'mpi': + _init_dist_mpi(backend, **kwargs) + elif launcher == 'slurm': + _init_dist_slurm(backend, **kwargs) + else: + raise ValueError(f'Invalid launcher type: {launcher}') + + +def _init_dist_pytorch(backend: str, **kwargs) -> None: + # TODO: use local_rank instead of rank % num_gpus + rank = int(os.environ['RANK']) + num_gpus = torch.cuda.device_count() + torch.cuda.set_device(rank % num_gpus) + dist.init_process_group(backend=backend, **kwargs) + + +def _init_dist_mpi(backend: str, **kwargs) -> None: + local_rank = int(os.environ['OMPI_COMM_WORLD_LOCAL_RANK']) + torch.cuda.set_device(local_rank) + if 'MASTER_PORT' not in os.environ: + # 29500 is torch.distributed default port + os.environ['MASTER_PORT'] = '29500' + if 'MASTER_ADDR' not in os.environ: + raise KeyError('The environment variable MASTER_ADDR is not set') + os.environ['WORLD_SIZE'] = os.environ['OMPI_COMM_WORLD_SIZE'] + os.environ['RANK'] = os.environ['OMPI_COMM_WORLD_RANK'] + dist.init_process_group(backend=backend, **kwargs) + + +def _init_dist_slurm(backend: str, port: Optional[int] = None) -> None: + """Initialize slurm distributed training environment. + + If argument ``port`` is not specified, then the master port will be system + environment variable ``MASTER_PORT``. If ``MASTER_PORT`` is not in system + environment variable, then a default port ``29500`` will be used. + + Args: + backend (str): Backend of torch.distributed. + port (int, optional): Master port. Defaults to None. + """ + proc_id = int(os.environ['SLURM_PROCID']) + ntasks = int(os.environ['SLURM_NTASKS']) + node_list = os.environ['SLURM_NODELIST'] + num_gpus = torch.cuda.device_count() + torch.cuda.set_device(proc_id % num_gpus) + addr = subprocess.getoutput( + f'scontrol show hostname {node_list} | head -n1') + # specify master port + if port is not None: + os.environ['MASTER_PORT'] = str(port) + elif 'MASTER_PORT' in os.environ: + pass # use MASTER_PORT in the environment variable + else: + # if torch.distributed default port(29500) is available + # then use it, else find a free port + if _is_free_port(29500): + os.environ['MASTER_PORT'] = '29500' + else: + os.environ['MASTER_PORT'] = str(_find_free_port()) + # use MASTER_ADDR in the environment variable if it already exists + if 'MASTER_ADDR' not in os.environ: + os.environ['MASTER_ADDR'] = addr + os.environ['WORLD_SIZE'] = str(ntasks) + os.environ['LOCAL_RANK'] = str(proc_id % num_gpus) + os.environ['RANK'] = str(proc_id) + dist.init_process_group(backend=backend) + + +def get_dist_info() -> Tuple[int, int]: + if dist.is_available() and dist.is_initialized(): + rank = dist.get_rank() + world_size = dist.get_world_size() + else: + rank = 0 + world_size = 1 + return rank, world_size + + +def master_only(func: Callable) -> Callable: + + @functools.wraps(func) + def wrapper(*args, **kwargs): + rank, _ = get_dist_info() + if rank == 0: + return func(*args, **kwargs) + + return wrapper + + +def allreduce_params(params: List[torch.nn.Parameter], + coalesce: bool = True, + bucket_size_mb: int = -1) -> None: + """Allreduce parameters. + + Args: + params (list[torch.nn.Parameter]): List of parameters or buffers + of a model. + coalesce (bool, optional): Whether allreduce parameters as a whole. + Defaults to True. + bucket_size_mb (int, optional): Size of bucket, the unit is MB. + Defaults to -1. + """ + _, world_size = get_dist_info() + if world_size == 1: + return + params = [param.data for param in params] + if coalesce: + _allreduce_coalesced(params, world_size, bucket_size_mb) + else: + for tensor in params: + dist.all_reduce(tensor.div_(world_size)) + + +def allreduce_grads(params: List[torch.nn.Parameter], + coalesce: bool = True, + bucket_size_mb: int = -1) -> None: + """Allreduce gradients. + + Args: + params (list[torch.nn.Parameter]): List of parameters of a model. + coalesce (bool, optional): Whether allreduce parameters as a whole. + Defaults to True. + bucket_size_mb (int, optional): Size of bucket, the unit is MB. + Defaults to -1. + """ + grads = [ + param.grad.data for param in params + if param.requires_grad and param.grad is not None + ] + _, world_size = get_dist_info() + if world_size == 1: + return + if coalesce: + _allreduce_coalesced(grads, world_size, bucket_size_mb) + else: + for tensor in grads: + dist.all_reduce(tensor.div_(world_size)) + + +def _allreduce_coalesced(tensors: torch.Tensor, + world_size: int, + bucket_size_mb: int = -1) -> None: + if bucket_size_mb > 0: + bucket_size_bytes = bucket_size_mb * 1024 * 1024 + buckets = _take_tensors(tensors, bucket_size_bytes) + else: + buckets = OrderedDict() + for tensor in tensors: + tp = tensor.type() + if tp not in buckets: + buckets[tp] = [] + buckets[tp].append(tensor) + buckets = buckets.values() + + for bucket in buckets: + flat_tensors = _flatten_dense_tensors(bucket) + dist.all_reduce(flat_tensors) + flat_tensors.div_(world_size) + for tensor, synced in zip( + bucket, _unflatten_dense_tensors(flat_tensors, bucket)): + tensor.copy_(synced) diff --git a/easy_ViTPose/vit_utils/inference.py b/easy_ViTPose/vit_utils/inference.py new file mode 100644 index 0000000000000000000000000000000000000000..70d41840ada28d080e53e7740a19525fba2a0bc5 --- /dev/null +++ b/easy_ViTPose/vit_utils/inference.py @@ -0,0 +1,93 @@ +import cv2 +import numpy as np +import json + + +rotation_map = { + 0: None, + 90: cv2.ROTATE_90_COUNTERCLOCKWISE, + 180: cv2.ROTATE_180, + 270: cv2.ROTATE_90_CLOCKWISE +} + +class NumpyEncoder(json.JSONEncoder): + def default(self, obj): + if isinstance(obj, np.ndarray): + return obj.tolist() + return json.JSONEncoder.default(self, obj) + +def draw_bboxes(image, bounding_boxes, boxes_id, scores): + image_with_boxes = image.copy() + + for bbox, bbox_id, score in zip(bounding_boxes, boxes_id, scores): + x1, y1, x2, y2 = bbox + cv2.rectangle(image_with_boxes, (x1, y1), (x2, y2), (128, 128, 0), 2) + + label = f'#{bbox_id}: {score:.2f}' + + (label_width, label_height), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1) + label_x = x1 + label_y = y1 - 5 if y1 > 20 else y1 + 20 + + # Draw a filled rectangle as the background for the label + cv2.rectangle(image_with_boxes, (x1, label_y - label_height - 5), + (x1 + label_width, label_y + 5), (128, 128, 0), cv2.FILLED) + cv2.putText(image_with_boxes, label, (label_x, label_y), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1) + + return image_with_boxes + + +def pad_image(image: np.ndarray, aspect_ratio: float) -> np.ndarray: + # Get the current aspect ratio of the image + image_height, image_width = image.shape[:2] + current_aspect_ratio = image_width / image_height + + left_pad = 0 + top_pad = 0 + # Determine whether to pad horizontally or vertically + if current_aspect_ratio < aspect_ratio: + # Pad horizontally + target_width = int(aspect_ratio * image_height) + pad_width = target_width - image_width + left_pad = pad_width // 2 + right_pad = pad_width - left_pad + + padded_image = np.pad(image, + pad_width=((0, 0), (left_pad, right_pad), (0, 0)), + mode='constant') + else: + # Pad vertically + target_height = int(image_width / aspect_ratio) + pad_height = target_height - image_height + top_pad = pad_height // 2 + bottom_pad = pad_height - top_pad + + padded_image = np.pad(image, + pad_width=((top_pad, bottom_pad), (0, 0), (0, 0)), + mode='constant') + return padded_image, (left_pad, top_pad) + + +class VideoReader(object): + def __init__(self, file_name, rotate=0): + self.file_name = file_name + self.rotate = rotation_map[rotate] + try: # OpenCV needs int to read from webcam + self.file_name = int(file_name) + except ValueError: + pass + + def __iter__(self): + self.cap = cv2.VideoCapture(self.file_name) + if not self.cap.isOpened(): + raise IOError('Video {} cannot be opened'.format(self.file_name)) + return self + + def __next__(self): + was_read, img = self.cap.read() + if not was_read: + raise StopIteration + if self.rotate is not None: + img = cv2.rotate(img, self.rotate) + return cv2.cvtColor(img, cv2.COLOR_BGR2RGB) diff --git a/easy_ViTPose/vit_utils/logging.py b/easy_ViTPose/vit_utils/logging.py new file mode 100644 index 0000000000000000000000000000000000000000..aeab3115cfbdaba436a9c94f496c87b5ecdc2bcd --- /dev/null +++ b/easy_ViTPose/vit_utils/logging.py @@ -0,0 +1,133 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import logging + +import torch.distributed as dist + +logger_initialized: dict = {} + + +def get_logger(name, log_file=None, log_level=logging.INFO, file_mode='w'): + """Initialize and get a logger by name. + + If the logger has not been initialized, this method will initialize the + logger by adding one or two handlers, otherwise the initialized logger will + be directly returned. During initialization, a StreamHandler will always be + added. If `log_file` is specified and the process rank is 0, a FileHandler + will also be added. + + Args: + name (str): Logger name. + log_file (str | None): The log filename. If specified, a FileHandler + will be added to the logger. + log_level (int): The logger level. Note that only the process of + rank 0 is affected, and other processes will set the level to + "Error" thus be silent most of the time. + file_mode (str): The file mode used in opening log file. + Defaults to 'w'. + + Returns: + logging.Logger: The expected logger. + """ + logger = logging.getLogger(name) + if name in logger_initialized: + return logger + # handle hierarchical names + # e.g., logger "a" is initialized, then logger "a.b" will skip the + # initialization since it is a child of "a". + for logger_name in logger_initialized: + if name.startswith(logger_name): + return logger + + # handle duplicate logs to the console + # Starting in 1.8.0, PyTorch DDP attaches a StreamHandler (NOTSET) + # to the root logger. As logger.propagate is True by default, this root + # level handler causes logging messages from rank>0 processes to + # unexpectedly show up on the console, creating much unwanted clutter. + # To fix this issue, we set the root logger's StreamHandler, if any, to log + # at the ERROR level. + for handler in logger.root.handlers: + if type(handler) is logging.StreamHandler: + handler.setLevel(logging.ERROR) + + stream_handler = logging.StreamHandler() + handlers = [stream_handler] + + if dist.is_available() and dist.is_initialized(): + rank = dist.get_rank() + else: + rank = 0 + + # only rank 0 will add a FileHandler + if rank == 0 and log_file is not None: + # Here, the default behaviour of the official logger is 'a'. Thus, we + # provide an interface to change the file mode to the default + # behaviour. + file_handler = logging.FileHandler(log_file, file_mode) + handlers.append(file_handler) + + formatter = logging.Formatter( + '%(asctime)s - %(name)s - %(levelname)s - %(message)s') + for handler in handlers: + handler.setFormatter(formatter) + handler.setLevel(log_level) + logger.addHandler(handler) + + if rank == 0: + logger.setLevel(log_level) + else: + logger.setLevel(logging.ERROR) + + logger_initialized[name] = True + + return logger + + +def print_log(msg, logger=None, level=logging.INFO): + """Print a log message. + + Args: + msg (str): The message to be logged. + logger (logging.Logger | str | None): The logger to be used. + Some special loggers are: + + - "silent": no message will be printed. + - other str: the logger obtained with `get_root_logger(logger)`. + - None: The `print()` method will be used to print log messages. + level (int): Logging level. Only available when `logger` is a Logger + object or "root". + """ + if logger is None: + print(msg) + elif isinstance(logger, logging.Logger): + logger.log(level, msg) + elif logger == 'silent': + pass + elif isinstance(logger, str): + _logger = get_logger(logger) + _logger.log(level, msg) + else: + raise TypeError( + 'logger should be either a logging.Logger object, str, ' + f'"silent" or None, but got {type(logger)}') + + +def get_root_logger(log_file=None, log_level=logging.INFO): + """Use `get_logger` method in mmcv to get the root logger. + + The logger will be initialized if it has not been initialized. By default a + StreamHandler will be added. If `log_file` is specified, a FileHandler will + also be added. The name of the root logger is the top-level package name, + e.g., "mmpose". + + Args: + log_file (str | None): The log filename. If specified, a FileHandler + will be added to the root logger. + log_level (int): The root logger level. Note that only the process of + rank 0 is affected, while other processes will set the level to + "Error" and be silent most of the time. + + Returns: + logging.Logger: The root logger. + """ + return get_logger(__name__.split('.')[0], log_file, log_level) + diff --git a/easy_ViTPose/vit_utils/nms/__init__.py b/easy_ViTPose/vit_utils/nms/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/easy_ViTPose/vit_utils/nms/cpu_nms.c b/easy_ViTPose/vit_utils/nms/cpu_nms.c new file mode 100644 index 0000000000000000000000000000000000000000..b0230b8659a43511aa82c37d40d810a5e18d6189 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/cpu_nms.c @@ -0,0 +1,7952 @@ +/* Generated by Cython 0.29.32 */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 +#define CYTHON_FUTURE_DIVISION 1 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif +#endif + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #endif +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#ifndef PyObject_Unicode + #define PyObject_Unicode PyObject_Str +#endif +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#define __PYX_MARK_ERR_POS(f_index, lineno) \ + { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__cpu_nms +#define __PYX_HAVE_API__cpu_nms +/* Early includes */ +#include +#include +#include "numpy/arrayobject.h" +#include "numpy/ndarrayobject.h" +#include "numpy/ndarraytypes.h" +#include "numpy/arrayscalars.h" +#include "numpy/ufuncobject.h" + + /* NumPy API declarations from "numpy/__init__.pxd" */ + +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + +/* Header.proto */ +#if !defined(CYTHON_CCOMPLEX) + #if defined(__cplusplus) + #define CYTHON_CCOMPLEX 1 + #elif defined(_Complex_I) + #define CYTHON_CCOMPLEX 1 + #else + #define CYTHON_CCOMPLEX 0 + #endif +#endif +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #include + #else + #include + #endif +#endif +#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) + #undef _Complex_I + #define _Complex_I 1.0fj +#endif + + +static const char *__pyx_f[] = { + "cpu_nms.pyx", + "__init__.pxd", + "type.pxd", +}; +/* BufferFormatStructs.proto */ +#define IS_UNSIGNED(type) (((type) -1) > 0) +struct __Pyx_StructField_; +#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) +typedef struct { + const char* name; + struct __Pyx_StructField_* fields; + size_t size; + size_t arraysize[8]; + int ndim; + char typegroup; + char is_unsigned; + int flags; +} __Pyx_TypeInfo; +typedef struct __Pyx_StructField_ { + __Pyx_TypeInfo* type; + const char* name; + size_t offset; +} __Pyx_StructField; +typedef struct { + __Pyx_StructField* field; + size_t parent_offset; +} __Pyx_BufFmt_StackElem; +typedef struct { + __Pyx_StructField root; + __Pyx_BufFmt_StackElem* head; + size_t fmt_offset; + size_t new_count, enc_count; + size_t struct_alignment; + int is_complex; + char enc_type; + char new_packmode; + char enc_packmode; + char is_valid_array; +} __Pyx_BufFmt_Context; + + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":690 + * # in Cython to enable them only on the right systems. + * + * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t + */ +typedef npy_int8 __pyx_t_5numpy_int8_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":691 + * + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t + */ +typedef npy_int16 __pyx_t_5numpy_int16_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":692 + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< + * ctypedef npy_int64 int64_t + * #ctypedef npy_int96 int96_t + */ +typedef npy_int32 __pyx_t_5numpy_int32_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":693 + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< + * #ctypedef npy_int96 int96_t + * #ctypedef npy_int128 int128_t + */ +typedef npy_int64 __pyx_t_5numpy_int64_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":697 + * #ctypedef npy_int128 int128_t + * + * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t + */ +typedef npy_uint8 __pyx_t_5numpy_uint8_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":698 + * + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t + */ +typedef npy_uint16 __pyx_t_5numpy_uint16_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":699 + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< + * ctypedef npy_uint64 uint64_t + * #ctypedef npy_uint96 uint96_t + */ +typedef npy_uint32 __pyx_t_5numpy_uint32_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":700 + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< + * #ctypedef npy_uint96 uint96_t + * #ctypedef npy_uint128 uint128_t + */ +typedef npy_uint64 __pyx_t_5numpy_uint64_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":704 + * #ctypedef npy_uint128 uint128_t + * + * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< + * ctypedef npy_float64 float64_t + * #ctypedef npy_float80 float80_t + */ +typedef npy_float32 __pyx_t_5numpy_float32_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":705 + * + * ctypedef npy_float32 float32_t + * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< + * #ctypedef npy_float80 float80_t + * #ctypedef npy_float128 float128_t + */ +typedef npy_float64 __pyx_t_5numpy_float64_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":714 + * # The int types are mapped a bit surprising -- + * # numpy.int corresponds to 'l' and numpy.long to 'q' + * ctypedef npy_long int_t # <<<<<<<<<<<<<< + * ctypedef npy_longlong long_t + * ctypedef npy_longlong longlong_t + */ +typedef npy_long __pyx_t_5numpy_int_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":715 + * # numpy.int corresponds to 'l' and numpy.long to 'q' + * ctypedef npy_long int_t + * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< + * ctypedef npy_longlong longlong_t + * + */ +typedef npy_longlong __pyx_t_5numpy_long_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":716 + * ctypedef npy_long int_t + * ctypedef npy_longlong long_t + * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< + * + * ctypedef npy_ulong uint_t + */ +typedef npy_longlong __pyx_t_5numpy_longlong_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":718 + * ctypedef npy_longlong longlong_t + * + * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< + * ctypedef npy_ulonglong ulong_t + * ctypedef npy_ulonglong ulonglong_t + */ +typedef npy_ulong __pyx_t_5numpy_uint_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":719 + * + * ctypedef npy_ulong uint_t + * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< + * ctypedef npy_ulonglong ulonglong_t + * + */ +typedef npy_ulonglong __pyx_t_5numpy_ulong_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":720 + * ctypedef npy_ulong uint_t + * ctypedef npy_ulonglong ulong_t + * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< + * + * ctypedef npy_intp intp_t + */ +typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":722 + * ctypedef npy_ulonglong ulonglong_t + * + * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< + * ctypedef npy_uintp uintp_t + * + */ +typedef npy_intp __pyx_t_5numpy_intp_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":723 + * + * ctypedef npy_intp intp_t + * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< + * + * ctypedef npy_double float_t + */ +typedef npy_uintp __pyx_t_5numpy_uintp_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":725 + * ctypedef npy_uintp uintp_t + * + * ctypedef npy_double float_t # <<<<<<<<<<<<<< + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t + */ +typedef npy_double __pyx_t_5numpy_float_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":726 + * + * ctypedef npy_double float_t + * ctypedef npy_double double_t # <<<<<<<<<<<<<< + * ctypedef npy_longdouble longdouble_t + * + */ +typedef npy_double __pyx_t_5numpy_double_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":727 + * ctypedef npy_double float_t + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< + * + * ctypedef npy_cfloat cfloat_t + */ +typedef npy_longdouble __pyx_t_5numpy_longdouble_t; +/* Declarations.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< float > __pyx_t_float_complex; + #else + typedef float _Complex __pyx_t_float_complex; + #endif +#else + typedef struct { float real, imag; } __pyx_t_float_complex; +#endif +static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); + +/* Declarations.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< double > __pyx_t_double_complex; + #else + typedef double _Complex __pyx_t_double_complex; + #endif +#else + typedef struct { double real, imag; } __pyx_t_double_complex; +#endif +static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); + + +/*--- Type declarations ---*/ + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":729 + * ctypedef npy_longdouble longdouble_t + * + * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< + * ctypedef npy_cdouble cdouble_t + * ctypedef npy_clongdouble clongdouble_t + */ +typedef npy_cfloat __pyx_t_5numpy_cfloat_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":730 + * + * ctypedef npy_cfloat cfloat_t + * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< + * ctypedef npy_clongdouble clongdouble_t + * + */ +typedef npy_cdouble __pyx_t_5numpy_cdouble_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":731 + * ctypedef npy_cfloat cfloat_t + * ctypedef npy_cdouble cdouble_t + * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< + * + * ctypedef npy_cdouble complex_t + */ +typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":733 + * ctypedef npy_clongdouble clongdouble_t + * + * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew1(a): + */ +typedef npy_cdouble __pyx_t_5numpy_complex_t; + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* ArgTypeTest.proto */ +#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ + ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\ + __Pyx__ArgTypeTest(obj, type, name, exact)) +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); + +/* IsLittleEndian.proto */ +static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); + +/* BufferFormatCheck.proto */ +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type); + +/* BufferGetAndValidate.proto */ +#define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)\ + ((obj == Py_None || obj == NULL) ?\ + (__Pyx_ZeroBuffer(buf), 0) :\ + __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)) +static int __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj, + __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); +static void __Pyx_ZeroBuffer(Py_buffer* buf); +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); +static Py_ssize_t __Pyx_minusones[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; +static Py_ssize_t __Pyx_zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* GetItemInt.proto */ +#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ + __Pyx_GetItemInt_Generic(o, to_py_func(i)))) +#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck); + +/* ObjectGetItem.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); +#else +#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) +#endif + +/* ExtTypeTest.proto */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +/* PyIntBinop.proto */ +#if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); +#else +#define __Pyx_PyInt_AddObjC(op1, op2, intval, inplace, zerodivision_check)\ + (inplace ? PyNumber_InPlaceAdd(op1, op2) : PyNumber_Add(op1, op2)) +#endif + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif +#if CYTHON_FAST_PYCALL + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectCall2Args.proto */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* BufferIndexError.proto */ +static void __Pyx_RaiseBufferIndexError(int axis); + +#define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0) +/* ListAppend.proto */ +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { + PyListObject* L = (PyListObject*) list; + Py_ssize_t len = Py_SIZE(list); + if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { + Py_INCREF(x); + PyList_SET_ITEM(list, len, x); + __Pyx_SET_SIZE(list, len + 1); + return 0; + } + return PyList_Append(list, x); +} +#else +#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) +#endif + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* GetTopmostException.proto */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* SaveResetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +#else +#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) +#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) +#endif + +/* PyErrExceptionMatches.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* GetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* RaiseException.proto */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto +#define __PYX_HAVE_RT_ImportType_proto +enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 +}; +static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); +#endif + +/* Import.proto */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* BufferStructDeclare.proto */ +typedef struct { + Py_ssize_t shape, strides, suboffsets; +} __Pyx_Buf_DimInfo; +typedef struct { + size_t refcount; + Py_buffer pybuffer; +} __Pyx_Buffer; +typedef struct { + __Pyx_Buffer *rcbuffer; + char *data; + __Pyx_Buf_DimInfo diminfo[8]; +} __Pyx_LocalBuf_ND; + +#if PY_MAJOR_VERSION < 3 + static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); + static void __Pyx_ReleaseBuffer(Py_buffer *view); +#else + #define __Pyx_GetBuffer PyObject_GetBuffer + #define __Pyx_ReleaseBuffer PyBuffer_Release +#endif + + +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* RealImag.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #define __Pyx_CREAL(z) ((z).real()) + #define __Pyx_CIMAG(z) ((z).imag()) + #else + #define __Pyx_CREAL(z) (__real__(z)) + #define __Pyx_CIMAG(z) (__imag__(z)) + #endif +#else + #define __Pyx_CREAL(z) ((z).real) + #define __Pyx_CIMAG(z) ((z).imag) +#endif +#if defined(__cplusplus) && CYTHON_CCOMPLEX\ + && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) + #define __Pyx_SET_CREAL(z,x) ((z).real(x)) + #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) +#else + #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) + #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) +#endif + +/* Arithmetic.proto */ +#if CYTHON_CCOMPLEX + #define __Pyx_c_eq_float(a, b) ((a)==(b)) + #define __Pyx_c_sum_float(a, b) ((a)+(b)) + #define __Pyx_c_diff_float(a, b) ((a)-(b)) + #define __Pyx_c_prod_float(a, b) ((a)*(b)) + #define __Pyx_c_quot_float(a, b) ((a)/(b)) + #define __Pyx_c_neg_float(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero_float(z) ((z)==(float)0) + #define __Pyx_c_conj_float(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs_float(z) (::std::abs(z)) + #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero_float(z) ((z)==0) + #define __Pyx_c_conj_float(z) (conjf(z)) + #if 1 + #define __Pyx_c_abs_float(z) (cabsf(z)) + #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); + static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); + #if 1 + static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); + #endif +#endif + +/* Arithmetic.proto */ +#if CYTHON_CCOMPLEX + #define __Pyx_c_eq_double(a, b) ((a)==(b)) + #define __Pyx_c_sum_double(a, b) ((a)+(b)) + #define __Pyx_c_diff_double(a, b) ((a)-(b)) + #define __Pyx_c_prod_double(a, b) ((a)*(b)) + #define __Pyx_c_quot_double(a, b) ((a)/(b)) + #define __Pyx_c_neg_double(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero_double(z) ((z)==(double)0) + #define __Pyx_c_conj_double(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs_double(z) (::std::abs(z)) + #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero_double(z) ((z)==0) + #define __Pyx_c_conj_double(z) (conj(z)) + #if 1 + #define __Pyx_c_abs_double(z) (cabs(z)) + #define __Pyx_c_pow_double(a, b) (cpow(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); + static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); + #if 1 + static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); + #endif +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + +/* Module declarations from 'cpython.buffer' */ + +/* Module declarations from 'libc.string' */ + +/* Module declarations from 'libc.stdio' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.type' */ +static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; + +/* Module declarations from 'cpython' */ + +/* Module declarations from 'cpython.object' */ + +/* Module declarations from 'cpython.ref' */ + +/* Module declarations from 'cpython.mem' */ + +/* Module declarations from 'numpy' */ + +/* Module declarations from 'numpy' */ +static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; +static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; +static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; +static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; +static PyTypeObject *__pyx_ptype_5numpy_generic = 0; +static PyTypeObject *__pyx_ptype_5numpy_number = 0; +static PyTypeObject *__pyx_ptype_5numpy_integer = 0; +static PyTypeObject *__pyx_ptype_5numpy_signedinteger = 0; +static PyTypeObject *__pyx_ptype_5numpy_unsignedinteger = 0; +static PyTypeObject *__pyx_ptype_5numpy_inexact = 0; +static PyTypeObject *__pyx_ptype_5numpy_floating = 0; +static PyTypeObject *__pyx_ptype_5numpy_complexfloating = 0; +static PyTypeObject *__pyx_ptype_5numpy_flexible = 0; +static PyTypeObject *__pyx_ptype_5numpy_character = 0; +static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; + +/* Module declarations from 'cpu_nms' */ +static CYTHON_INLINE __pyx_t_5numpy_float32_t __pyx_f_7cpu_nms_max(__pyx_t_5numpy_float32_t, __pyx_t_5numpy_float32_t); /*proto*/ +static CYTHON_INLINE __pyx_t_5numpy_float32_t __pyx_f_7cpu_nms_min(__pyx_t_5numpy_float32_t, __pyx_t_5numpy_float32_t); /*proto*/ +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t = { "float32_t", NULL, sizeof(__pyx_t_5numpy_float32_t), { 0 }, 0, 'R', 0, 0 }; +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int_t = { "int_t", NULL, sizeof(__pyx_t_5numpy_int_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_int_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_int_t), 0 }; +#define __Pyx_MODULE_NAME "cpu_nms" +extern int __pyx_module_is_main_cpu_nms; +int __pyx_module_is_main_cpu_nms = 0; + +/* Implementation of 'cpu_nms' */ +static PyObject *__pyx_builtin_range; +static PyObject *__pyx_builtin_ImportError; +static const char __pyx_k_h[] = "h"; +static const char __pyx_k_i[] = "i"; +static const char __pyx_k_j[] = "_j"; +static const char __pyx_k_w[] = "w"; +static const char __pyx_k_np[] = "np"; +static const char __pyx_k_x1[] = "x1"; +static const char __pyx_k_x2[] = "x2"; +static const char __pyx_k_y1[] = "y1"; +static const char __pyx_k_y2[] = "y2"; +static const char __pyx_k_i_2[] = "_i"; +static const char __pyx_k_int[] = "int"; +static const char __pyx_k_ix1[] = "ix1"; +static const char __pyx_k_ix2[] = "ix2"; +static const char __pyx_k_iy1[] = "iy1"; +static const char __pyx_k_iy2[] = "iy2"; +static const char __pyx_k_j_2[] = "j"; +static const char __pyx_k_ovr[] = "ovr"; +static const char __pyx_k_xx1[] = "xx1"; +static const char __pyx_k_xx2[] = "xx2"; +static const char __pyx_k_yy1[] = "yy1"; +static const char __pyx_k_yy2[] = "yy2"; +static const char __pyx_k_dets[] = "dets"; +static const char __pyx_k_keep[] = "keep"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_areas[] = "areas"; +static const char __pyx_k_dtype[] = "dtype"; +static const char __pyx_k_iarea[] = "iarea"; +static const char __pyx_k_inter[] = "inter"; +static const char __pyx_k_ndets[] = "ndets"; +static const char __pyx_k_numpy[] = "numpy"; +static const char __pyx_k_order[] = "order"; +static const char __pyx_k_range[] = "range"; +static const char __pyx_k_zeros[] = "zeros"; +static const char __pyx_k_astype[] = "astype"; +static const char __pyx_k_import[] = "__import__"; +static const char __pyx_k_scores[] = "scores"; +static const char __pyx_k_thresh[] = "thresh"; +static const char __pyx_k_argsort[] = "argsort"; +static const char __pyx_k_cpu_nms[] = "cpu_nms"; +static const char __pyx_k_suppressed[] = "suppressed"; +static const char __pyx_k_ImportError[] = "ImportError"; +static const char __pyx_k_cpu_nms_pyx[] = "cpu_nms.pyx"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_numpy_core_multiarray_failed_to[] = "numpy.core.multiarray failed to import"; +static const char __pyx_k_numpy_core_umath_failed_to_impor[] = "numpy.core.umath failed to import"; +static PyObject *__pyx_n_s_ImportError; +static PyObject *__pyx_n_s_areas; +static PyObject *__pyx_n_s_argsort; +static PyObject *__pyx_n_s_astype; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_cpu_nms; +static PyObject *__pyx_kp_s_cpu_nms_pyx; +static PyObject *__pyx_n_s_dets; +static PyObject *__pyx_n_s_dtype; +static PyObject *__pyx_n_s_h; +static PyObject *__pyx_n_s_i; +static PyObject *__pyx_n_s_i_2; +static PyObject *__pyx_n_s_iarea; +static PyObject *__pyx_n_s_import; +static PyObject *__pyx_n_s_int; +static PyObject *__pyx_n_s_inter; +static PyObject *__pyx_n_s_ix1; +static PyObject *__pyx_n_s_ix2; +static PyObject *__pyx_n_s_iy1; +static PyObject *__pyx_n_s_iy2; +static PyObject *__pyx_n_s_j; +static PyObject *__pyx_n_s_j_2; +static PyObject *__pyx_n_s_keep; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_ndets; +static PyObject *__pyx_n_s_np; +static PyObject *__pyx_n_s_numpy; +static PyObject *__pyx_kp_s_numpy_core_multiarray_failed_to; +static PyObject *__pyx_kp_s_numpy_core_umath_failed_to_impor; +static PyObject *__pyx_n_s_order; +static PyObject *__pyx_n_s_ovr; +static PyObject *__pyx_n_s_range; +static PyObject *__pyx_n_s_scores; +static PyObject *__pyx_n_s_suppressed; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_n_s_thresh; +static PyObject *__pyx_n_s_w; +static PyObject *__pyx_n_s_x1; +static PyObject *__pyx_n_s_x2; +static PyObject *__pyx_n_s_xx1; +static PyObject *__pyx_n_s_xx2; +static PyObject *__pyx_n_s_y1; +static PyObject *__pyx_n_s_y2; +static PyObject *__pyx_n_s_yy1; +static PyObject *__pyx_n_s_yy2; +static PyObject *__pyx_n_s_zeros; +static PyObject *__pyx_pf_7cpu_nms_cpu_nms(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_dets, PyObject *__pyx_v_thresh); /* proto */ +static PyObject *__pyx_int_0; +static PyObject *__pyx_int_1; +static PyObject *__pyx_int_2; +static PyObject *__pyx_int_3; +static PyObject *__pyx_int_4; +static PyObject *__pyx_int_neg_1; +static PyObject *__pyx_slice_; +static PyObject *__pyx_slice__7; +static PyObject *__pyx_tuple__2; +static PyObject *__pyx_tuple__3; +static PyObject *__pyx_tuple__4; +static PyObject *__pyx_tuple__5; +static PyObject *__pyx_tuple__6; +static PyObject *__pyx_tuple__8; +static PyObject *__pyx_tuple__9; +static PyObject *__pyx_tuple__10; +static PyObject *__pyx_codeobj__11; +/* Late includes */ + +/* "cpu_nms.pyx":14 + * cimport numpy as np + * + * cdef inline np.float32_t max(np.float32_t a, np.float32_t b): # <<<<<<<<<<<<<< + * return a if a >= b else b + * + */ + +static CYTHON_INLINE __pyx_t_5numpy_float32_t __pyx_f_7cpu_nms_max(__pyx_t_5numpy_float32_t __pyx_v_a, __pyx_t_5numpy_float32_t __pyx_v_b) { + __pyx_t_5numpy_float32_t __pyx_r; + __Pyx_RefNannyDeclarations + __pyx_t_5numpy_float32_t __pyx_t_1; + __Pyx_RefNannySetupContext("max", 0); + + /* "cpu_nms.pyx":15 + * + * cdef inline np.float32_t max(np.float32_t a, np.float32_t b): + * return a if a >= b else b # <<<<<<<<<<<<<< + * + * cdef inline np.float32_t min(np.float32_t a, np.float32_t b): + */ + if (((__pyx_v_a >= __pyx_v_b) != 0)) { + __pyx_t_1 = __pyx_v_a; + } else { + __pyx_t_1 = __pyx_v_b; + } + __pyx_r = __pyx_t_1; + goto __pyx_L0; + + /* "cpu_nms.pyx":14 + * cimport numpy as np + * + * cdef inline np.float32_t max(np.float32_t a, np.float32_t b): # <<<<<<<<<<<<<< + * return a if a >= b else b + * + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "cpu_nms.pyx":17 + * return a if a >= b else b + * + * cdef inline np.float32_t min(np.float32_t a, np.float32_t b): # <<<<<<<<<<<<<< + * return a if a <= b else b + * + */ + +static CYTHON_INLINE __pyx_t_5numpy_float32_t __pyx_f_7cpu_nms_min(__pyx_t_5numpy_float32_t __pyx_v_a, __pyx_t_5numpy_float32_t __pyx_v_b) { + __pyx_t_5numpy_float32_t __pyx_r; + __Pyx_RefNannyDeclarations + __pyx_t_5numpy_float32_t __pyx_t_1; + __Pyx_RefNannySetupContext("min", 0); + + /* "cpu_nms.pyx":18 + * + * cdef inline np.float32_t min(np.float32_t a, np.float32_t b): + * return a if a <= b else b # <<<<<<<<<<<<<< + * + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): + */ + if (((__pyx_v_a <= __pyx_v_b) != 0)) { + __pyx_t_1 = __pyx_v_a; + } else { + __pyx_t_1 = __pyx_v_b; + } + __pyx_r = __pyx_t_1; + goto __pyx_L0; + + /* "cpu_nms.pyx":17 + * return a if a >= b else b + * + * cdef inline np.float32_t min(np.float32_t a, np.float32_t b): # <<<<<<<<<<<<<< + * return a if a <= b else b + * + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "cpu_nms.pyx":20 + * return a if a <= b else b + * + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_7cpu_nms_1cpu_nms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_7cpu_nms_1cpu_nms = {"cpu_nms", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7cpu_nms_1cpu_nms, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_7cpu_nms_1cpu_nms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyArrayObject *__pyx_v_dets = 0; + PyObject *__pyx_v_thresh = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("cpu_nms (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_dets,&__pyx_n_s_thresh,0}; + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_dets)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_thresh)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("cpu_nms", 1, 2, 2, 1); __PYX_ERR(0, 20, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "cpu_nms") < 0)) __PYX_ERR(0, 20, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_dets = ((PyArrayObject *)values[0]); + __pyx_v_thresh = ((PyObject*)values[1]); + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("cpu_nms", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 20, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("cpu_nms.cpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dets), __pyx_ptype_5numpy_ndarray, 1, "dets", 0))) __PYX_ERR(0, 20, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_thresh), (&PyFloat_Type), 1, "thresh", 1))) __PYX_ERR(0, 20, __pyx_L1_error) + __pyx_r = __pyx_pf_7cpu_nms_cpu_nms(__pyx_self, __pyx_v_dets, __pyx_v_thresh); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_7cpu_nms_cpu_nms(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_dets, PyObject *__pyx_v_thresh) { + PyArrayObject *__pyx_v_x1 = 0; + PyArrayObject *__pyx_v_y1 = 0; + PyArrayObject *__pyx_v_x2 = 0; + PyArrayObject *__pyx_v_y2 = 0; + PyArrayObject *__pyx_v_scores = 0; + PyArrayObject *__pyx_v_areas = 0; + PyArrayObject *__pyx_v_order = 0; + int __pyx_v_ndets; + PyArrayObject *__pyx_v_suppressed = 0; + int __pyx_v__i; + int __pyx_v__j; + int __pyx_v_i; + int __pyx_v_j; + __pyx_t_5numpy_float32_t __pyx_v_ix1; + __pyx_t_5numpy_float32_t __pyx_v_iy1; + __pyx_t_5numpy_float32_t __pyx_v_ix2; + __pyx_t_5numpy_float32_t __pyx_v_iy2; + __pyx_t_5numpy_float32_t __pyx_v_iarea; + __pyx_t_5numpy_float32_t __pyx_v_xx1; + __pyx_t_5numpy_float32_t __pyx_v_yy1; + __pyx_t_5numpy_float32_t __pyx_v_xx2; + __pyx_t_5numpy_float32_t __pyx_v_yy2; + __pyx_t_5numpy_float32_t __pyx_v_w; + __pyx_t_5numpy_float32_t __pyx_v_h; + __pyx_t_5numpy_float32_t __pyx_v_inter; + __pyx_t_5numpy_float32_t __pyx_v_ovr; + PyObject *__pyx_v_keep = NULL; + __Pyx_LocalBuf_ND __pyx_pybuffernd_areas; + __Pyx_Buffer __pyx_pybuffer_areas; + __Pyx_LocalBuf_ND __pyx_pybuffernd_dets; + __Pyx_Buffer __pyx_pybuffer_dets; + __Pyx_LocalBuf_ND __pyx_pybuffernd_order; + __Pyx_Buffer __pyx_pybuffer_order; + __Pyx_LocalBuf_ND __pyx_pybuffernd_scores; + __Pyx_Buffer __pyx_pybuffer_scores; + __Pyx_LocalBuf_ND __pyx_pybuffernd_suppressed; + __Pyx_Buffer __pyx_pybuffer_suppressed; + __Pyx_LocalBuf_ND __pyx_pybuffernd_x1; + __Pyx_Buffer __pyx_pybuffer_x1; + __Pyx_LocalBuf_ND __pyx_pybuffernd_x2; + __Pyx_Buffer __pyx_pybuffer_x2; + __Pyx_LocalBuf_ND __pyx_pybuffernd_y1; + __Pyx_Buffer __pyx_pybuffer_y1; + __Pyx_LocalBuf_ND __pyx_pybuffernd_y2; + __Pyx_Buffer __pyx_pybuffer_y2; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyArrayObject *__pyx_t_2 = NULL; + PyArrayObject *__pyx_t_3 = NULL; + PyArrayObject *__pyx_t_4 = NULL; + PyArrayObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyArrayObject *__pyx_t_9 = NULL; + PyObject *__pyx_t_10 = NULL; + PyArrayObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyArrayObject *__pyx_t_13 = NULL; + int __pyx_t_14; + int __pyx_t_15; + int __pyx_t_16; + Py_ssize_t __pyx_t_17; + int __pyx_t_18; + int __pyx_t_19; + int __pyx_t_20; + int __pyx_t_21; + int __pyx_t_22; + int __pyx_t_23; + __pyx_t_5numpy_float32_t __pyx_t_24; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("cpu_nms", 0); + __pyx_pybuffer_x1.pybuffer.buf = NULL; + __pyx_pybuffer_x1.refcount = 0; + __pyx_pybuffernd_x1.data = NULL; + __pyx_pybuffernd_x1.rcbuffer = &__pyx_pybuffer_x1; + __pyx_pybuffer_y1.pybuffer.buf = NULL; + __pyx_pybuffer_y1.refcount = 0; + __pyx_pybuffernd_y1.data = NULL; + __pyx_pybuffernd_y1.rcbuffer = &__pyx_pybuffer_y1; + __pyx_pybuffer_x2.pybuffer.buf = NULL; + __pyx_pybuffer_x2.refcount = 0; + __pyx_pybuffernd_x2.data = NULL; + __pyx_pybuffernd_x2.rcbuffer = &__pyx_pybuffer_x2; + __pyx_pybuffer_y2.pybuffer.buf = NULL; + __pyx_pybuffer_y2.refcount = 0; + __pyx_pybuffernd_y2.data = NULL; + __pyx_pybuffernd_y2.rcbuffer = &__pyx_pybuffer_y2; + __pyx_pybuffer_scores.pybuffer.buf = NULL; + __pyx_pybuffer_scores.refcount = 0; + __pyx_pybuffernd_scores.data = NULL; + __pyx_pybuffernd_scores.rcbuffer = &__pyx_pybuffer_scores; + __pyx_pybuffer_areas.pybuffer.buf = NULL; + __pyx_pybuffer_areas.refcount = 0; + __pyx_pybuffernd_areas.data = NULL; + __pyx_pybuffernd_areas.rcbuffer = &__pyx_pybuffer_areas; + __pyx_pybuffer_order.pybuffer.buf = NULL; + __pyx_pybuffer_order.refcount = 0; + __pyx_pybuffernd_order.data = NULL; + __pyx_pybuffernd_order.rcbuffer = &__pyx_pybuffer_order; + __pyx_pybuffer_suppressed.pybuffer.buf = NULL; + __pyx_pybuffer_suppressed.refcount = 0; + __pyx_pybuffernd_suppressed.data = NULL; + __pyx_pybuffernd_suppressed.rcbuffer = &__pyx_pybuffer_suppressed; + __pyx_pybuffer_dets.pybuffer.buf = NULL; + __pyx_pybuffer_dets.refcount = 0; + __pyx_pybuffernd_dets.data = NULL; + __pyx_pybuffernd_dets.rcbuffer = &__pyx_pybuffer_dets; + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dets.rcbuffer->pybuffer, (PyObject*)__pyx_v_dets, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) __PYX_ERR(0, 20, __pyx_L1_error) + } + __pyx_pybuffernd_dets.diminfo[0].strides = __pyx_pybuffernd_dets.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_dets.diminfo[0].shape = __pyx_pybuffernd_dets.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_dets.diminfo[1].strides = __pyx_pybuffernd_dets.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_dets.diminfo[1].shape = __pyx_pybuffernd_dets.rcbuffer->pybuffer.shape[1]; + + /* "cpu_nms.pyx":21 + * + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + */ + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_tuple__2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 21, __pyx_L1_error) + __pyx_t_2 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_x1.rcbuffer->pybuffer, (PyObject*)__pyx_t_2, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_x1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_x1.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 21, __pyx_L1_error) + } else {__pyx_pybuffernd_x1.diminfo[0].strides = __pyx_pybuffernd_x1.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_x1.diminfo[0].shape = __pyx_pybuffernd_x1.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_2 = 0; + __pyx_v_x1 = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "cpu_nms.pyx":22 + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] + */ + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_tuple__3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_3 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_y1.rcbuffer->pybuffer, (PyObject*)__pyx_t_3, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_y1 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_y1.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 22, __pyx_L1_error) + } else {__pyx_pybuffernd_y1.diminfo[0].strides = __pyx_pybuffernd_y1.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_y1.diminfo[0].shape = __pyx_pybuffernd_y1.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_3 = 0; + __pyx_v_y1 = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "cpu_nms.pyx":23 + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] + * cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] + */ + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_tuple__4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 23, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 23, __pyx_L1_error) + __pyx_t_4 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_x2.rcbuffer->pybuffer, (PyObject*)__pyx_t_4, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_x2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_x2.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 23, __pyx_L1_error) + } else {__pyx_pybuffernd_x2.diminfo[0].strides = __pyx_pybuffernd_x2.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_x2.diminfo[0].shape = __pyx_pybuffernd_x2.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_4 = 0; + __pyx_v_x2 = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "cpu_nms.pyx":24 + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] + * + */ + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_tuple__5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 24, __pyx_L1_error) + __pyx_t_5 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_y2.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_y2 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_y2.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 24, __pyx_L1_error) + } else {__pyx_pybuffernd_y2.diminfo[0].strides = __pyx_pybuffernd_y2.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_y2.diminfo[0].shape = __pyx_pybuffernd_y2.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_5 = 0; + __pyx_v_y2 = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "cpu_nms.pyx":25 + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] + * cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] # <<<<<<<<<<<<<< + * + * cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1) + */ + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_tuple__6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 25, __pyx_L1_error) + __pyx_t_6 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_scores.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_scores = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_scores.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 25, __pyx_L1_error) + } else {__pyx_pybuffernd_scores.diminfo[0].strides = __pyx_pybuffernd_scores.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_scores.diminfo[0].shape = __pyx_pybuffernd_scores.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_6 = 0; + __pyx_v_scores = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "cpu_nms.pyx":27 + * cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] + * + * cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1) # <<<<<<<<<<<<<< + * cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1].astype('i') + * + */ + __pyx_t_1 = PyNumber_Subtract(((PyObject *)__pyx_v_x2), ((PyObject *)__pyx_v_x1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyInt_AddObjC(__pyx_t_1, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyNumber_Subtract(((PyObject *)__pyx_v_y2), ((PyObject *)__pyx_v_y1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = __Pyx_PyInt_AddObjC(__pyx_t_1, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyNumber_Multiply(__pyx_t_7, __pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 27, __pyx_L1_error) + __pyx_t_9 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_areas.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_areas = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_areas.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 27, __pyx_L1_error) + } else {__pyx_pybuffernd_areas.diminfo[0].strides = __pyx_pybuffernd_areas.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_areas.diminfo[0].shape = __pyx_pybuffernd_areas.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_9 = 0; + __pyx_v_areas = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "cpu_nms.pyx":28 + * + * cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1) + * cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1].astype('i') # <<<<<<<<<<<<<< + * + * cdef int ndets = dets.shape[0] + */ + __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_scores), __pyx_n_s_argsort); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_10 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { + __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_7); + if (likely(__pyx_t_10)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_7, function); + } + } + __pyx_t_8 = (__pyx_t_10) ? __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_10) : __Pyx_PyObject_CallNoArg(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; + if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_t_8, __pyx_slice__7); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_astype); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_8, function); + } + } + __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_7, __pyx_n_s_i) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_n_s_i); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 28, __pyx_L1_error) + __pyx_t_11 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_order.rcbuffer->pybuffer, (PyObject*)__pyx_t_11, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_order = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_order.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 28, __pyx_L1_error) + } else {__pyx_pybuffernd_order.diminfo[0].strides = __pyx_pybuffernd_order.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_order.diminfo[0].shape = __pyx_pybuffernd_order.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_11 = 0; + __pyx_v_order = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "cpu_nms.pyx":30 + * cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1].astype('i') + * + * cdef int ndets = dets.shape[0] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.int_t, ndim=1] suppressed = \ + * np.zeros((ndets), dtype=np.int) + */ + __pyx_v_ndets = (__pyx_v_dets->dimensions[0]); + + /* "cpu_nms.pyx":32 + * cdef int ndets = dets.shape[0] + * cdef np.ndarray[np.int_t, ndim=1] suppressed = \ + * np.zeros((ndets), dtype=np.int) # <<<<<<<<<<<<<< + * + * # nominal indices + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_ndets); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_n_s_np); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_10); + __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_int); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_12) < 0) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_7, __pyx_t_1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 32, __pyx_L1_error) + __pyx_t_13 = ((PyArrayObject *)__pyx_t_12); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_suppressed.rcbuffer->pybuffer, (PyObject*)__pyx_t_13, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) { + __pyx_v_suppressed = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_suppressed.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 31, __pyx_L1_error) + } else {__pyx_pybuffernd_suppressed.diminfo[0].strides = __pyx_pybuffernd_suppressed.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_suppressed.diminfo[0].shape = __pyx_pybuffernd_suppressed.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_13 = 0; + __pyx_v_suppressed = ((PyArrayObject *)__pyx_t_12); + __pyx_t_12 = 0; + + /* "cpu_nms.pyx":45 + * cdef np.float32_t inter, ovr + * + * keep = [] # <<<<<<<<<<<<<< + * for _i in range(ndets): + * i = order[_i] + */ + __pyx_t_12 = PyList_New(0); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 45, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __pyx_v_keep = ((PyObject*)__pyx_t_12); + __pyx_t_12 = 0; + + /* "cpu_nms.pyx":46 + * + * keep = [] + * for _i in range(ndets): # <<<<<<<<<<<<<< + * i = order[_i] + * if suppressed[i] == 1: + */ + __pyx_t_14 = __pyx_v_ndets; + __pyx_t_15 = __pyx_t_14; + for (__pyx_t_16 = 0; __pyx_t_16 < __pyx_t_15; __pyx_t_16+=1) { + __pyx_v__i = __pyx_t_16; + + /* "cpu_nms.pyx":47 + * keep = [] + * for _i in range(ndets): + * i = order[_i] # <<<<<<<<<<<<<< + * if suppressed[i] == 1: + * continue + */ + __pyx_t_17 = __pyx_v__i; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_order.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_order.diminfo[0].shape)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + __PYX_ERR(0, 47, __pyx_L1_error) + } + __pyx_v_i = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_pybuffernd_order.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_order.diminfo[0].strides)); + + /* "cpu_nms.pyx":48 + * for _i in range(ndets): + * i = order[_i] + * if suppressed[i] == 1: # <<<<<<<<<<<<<< + * continue + * keep.append(i) + */ + __pyx_t_17 = __pyx_v_i; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_suppressed.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_suppressed.diminfo[0].shape)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + __PYX_ERR(0, 48, __pyx_L1_error) + } + __pyx_t_19 = (((*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_pybuffernd_suppressed.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_suppressed.diminfo[0].strides)) == 1) != 0); + if (__pyx_t_19) { + + /* "cpu_nms.pyx":49 + * i = order[_i] + * if suppressed[i] == 1: + * continue # <<<<<<<<<<<<<< + * keep.append(i) + * ix1 = x1[i] + */ + goto __pyx_L3_continue; + + /* "cpu_nms.pyx":48 + * for _i in range(ndets): + * i = order[_i] + * if suppressed[i] == 1: # <<<<<<<<<<<<<< + * continue + * keep.append(i) + */ + } + + /* "cpu_nms.pyx":50 + * if suppressed[i] == 1: + * continue + * keep.append(i) # <<<<<<<<<<<<<< + * ix1 = x1[i] + * iy1 = y1[i] + */ + __pyx_t_12 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_keep, __pyx_t_12); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + + /* "cpu_nms.pyx":51 + * continue + * keep.append(i) + * ix1 = x1[i] # <<<<<<<<<<<<<< + * iy1 = y1[i] + * ix2 = x2[i] + */ + __pyx_t_17 = __pyx_v_i; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_x1.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_x1.diminfo[0].shape)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + __PYX_ERR(0, 51, __pyx_L1_error) + } + __pyx_v_ix1 = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_x1.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_x1.diminfo[0].strides)); + + /* "cpu_nms.pyx":52 + * keep.append(i) + * ix1 = x1[i] + * iy1 = y1[i] # <<<<<<<<<<<<<< + * ix2 = x2[i] + * iy2 = y2[i] + */ + __pyx_t_17 = __pyx_v_i; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_y1.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_y1.diminfo[0].shape)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + __PYX_ERR(0, 52, __pyx_L1_error) + } + __pyx_v_iy1 = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_y1.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_y1.diminfo[0].strides)); + + /* "cpu_nms.pyx":53 + * ix1 = x1[i] + * iy1 = y1[i] + * ix2 = x2[i] # <<<<<<<<<<<<<< + * iy2 = y2[i] + * iarea = areas[i] + */ + __pyx_t_17 = __pyx_v_i; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_x2.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_x2.diminfo[0].shape)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + __PYX_ERR(0, 53, __pyx_L1_error) + } + __pyx_v_ix2 = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_x2.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_x2.diminfo[0].strides)); + + /* "cpu_nms.pyx":54 + * iy1 = y1[i] + * ix2 = x2[i] + * iy2 = y2[i] # <<<<<<<<<<<<<< + * iarea = areas[i] + * for _j in range(_i + 1, ndets): + */ + __pyx_t_17 = __pyx_v_i; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_y2.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_y2.diminfo[0].shape)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + __PYX_ERR(0, 54, __pyx_L1_error) + } + __pyx_v_iy2 = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_y2.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_y2.diminfo[0].strides)); + + /* "cpu_nms.pyx":55 + * ix2 = x2[i] + * iy2 = y2[i] + * iarea = areas[i] # <<<<<<<<<<<<<< + * for _j in range(_i + 1, ndets): + * j = order[_j] + */ + __pyx_t_17 = __pyx_v_i; + __pyx_t_18 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_areas.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_18 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_areas.diminfo[0].shape)) __pyx_t_18 = 0; + if (unlikely(__pyx_t_18 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_18); + __PYX_ERR(0, 55, __pyx_L1_error) + } + __pyx_v_iarea = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_areas.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_areas.diminfo[0].strides)); + + /* "cpu_nms.pyx":56 + * iy2 = y2[i] + * iarea = areas[i] + * for _j in range(_i + 1, ndets): # <<<<<<<<<<<<<< + * j = order[_j] + * if suppressed[j] == 1: + */ + __pyx_t_18 = __pyx_v_ndets; + __pyx_t_21 = __pyx_t_18; + for (__pyx_t_22 = (__pyx_v__i + 1); __pyx_t_22 < __pyx_t_21; __pyx_t_22+=1) { + __pyx_v__j = __pyx_t_22; + + /* "cpu_nms.pyx":57 + * iarea = areas[i] + * for _j in range(_i + 1, ndets): + * j = order[_j] # <<<<<<<<<<<<<< + * if suppressed[j] == 1: + * continue + */ + __pyx_t_17 = __pyx_v__j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_order.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_order.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 57, __pyx_L1_error) + } + __pyx_v_j = (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_pybuffernd_order.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_order.diminfo[0].strides)); + + /* "cpu_nms.pyx":58 + * for _j in range(_i + 1, ndets): + * j = order[_j] + * if suppressed[j] == 1: # <<<<<<<<<<<<<< + * continue + * xx1 = max(ix1, x1[j]) + */ + __pyx_t_17 = __pyx_v_j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_suppressed.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_suppressed.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 58, __pyx_L1_error) + } + __pyx_t_19 = (((*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_pybuffernd_suppressed.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_suppressed.diminfo[0].strides)) == 1) != 0); + if (__pyx_t_19) { + + /* "cpu_nms.pyx":59 + * j = order[_j] + * if suppressed[j] == 1: + * continue # <<<<<<<<<<<<<< + * xx1 = max(ix1, x1[j]) + * yy1 = max(iy1, y1[j]) + */ + goto __pyx_L6_continue; + + /* "cpu_nms.pyx":58 + * for _j in range(_i + 1, ndets): + * j = order[_j] + * if suppressed[j] == 1: # <<<<<<<<<<<<<< + * continue + * xx1 = max(ix1, x1[j]) + */ + } + + /* "cpu_nms.pyx":60 + * if suppressed[j] == 1: + * continue + * xx1 = max(ix1, x1[j]) # <<<<<<<<<<<<<< + * yy1 = max(iy1, y1[j]) + * xx2 = min(ix2, x2[j]) + */ + __pyx_t_17 = __pyx_v_j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_x1.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_x1.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 60, __pyx_L1_error) + } + __pyx_v_xx1 = __pyx_f_7cpu_nms_max(__pyx_v_ix1, (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_x1.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_x1.diminfo[0].strides))); + + /* "cpu_nms.pyx":61 + * continue + * xx1 = max(ix1, x1[j]) + * yy1 = max(iy1, y1[j]) # <<<<<<<<<<<<<< + * xx2 = min(ix2, x2[j]) + * yy2 = min(iy2, y2[j]) + */ + __pyx_t_17 = __pyx_v_j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_y1.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_y1.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 61, __pyx_L1_error) + } + __pyx_v_yy1 = __pyx_f_7cpu_nms_max(__pyx_v_iy1, (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_y1.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_y1.diminfo[0].strides))); + + /* "cpu_nms.pyx":62 + * xx1 = max(ix1, x1[j]) + * yy1 = max(iy1, y1[j]) + * xx2 = min(ix2, x2[j]) # <<<<<<<<<<<<<< + * yy2 = min(iy2, y2[j]) + * w = max(0.0, xx2 - xx1 + 1) + */ + __pyx_t_17 = __pyx_v_j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_x2.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_x2.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 62, __pyx_L1_error) + } + __pyx_v_xx2 = __pyx_f_7cpu_nms_min(__pyx_v_ix2, (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_x2.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_x2.diminfo[0].strides))); + + /* "cpu_nms.pyx":63 + * yy1 = max(iy1, y1[j]) + * xx2 = min(ix2, x2[j]) + * yy2 = min(iy2, y2[j]) # <<<<<<<<<<<<<< + * w = max(0.0, xx2 - xx1 + 1) + * h = max(0.0, yy2 - yy1 + 1) + */ + __pyx_t_17 = __pyx_v_j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_y2.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_y2.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 63, __pyx_L1_error) + } + __pyx_v_yy2 = __pyx_f_7cpu_nms_min(__pyx_v_iy2, (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_y2.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_y2.diminfo[0].strides))); + + /* "cpu_nms.pyx":64 + * xx2 = min(ix2, x2[j]) + * yy2 = min(iy2, y2[j]) + * w = max(0.0, xx2 - xx1 + 1) # <<<<<<<<<<<<<< + * h = max(0.0, yy2 - yy1 + 1) + * inter = w * h + */ + __pyx_v_w = __pyx_f_7cpu_nms_max(0.0, ((__pyx_v_xx2 - __pyx_v_xx1) + 1.0)); + + /* "cpu_nms.pyx":65 + * yy2 = min(iy2, y2[j]) + * w = max(0.0, xx2 - xx1 + 1) + * h = max(0.0, yy2 - yy1 + 1) # <<<<<<<<<<<<<< + * inter = w * h + * ovr = inter / (iarea + areas[j] - inter) + */ + __pyx_v_h = __pyx_f_7cpu_nms_max(0.0, ((__pyx_v_yy2 - __pyx_v_yy1) + 1.0)); + + /* "cpu_nms.pyx":66 + * w = max(0.0, xx2 - xx1 + 1) + * h = max(0.0, yy2 - yy1 + 1) + * inter = w * h # <<<<<<<<<<<<<< + * ovr = inter / (iarea + areas[j] - inter) + * if ovr >= thresh: + */ + __pyx_v_inter = (__pyx_v_w * __pyx_v_h); + + /* "cpu_nms.pyx":67 + * h = max(0.0, yy2 - yy1 + 1) + * inter = w * h + * ovr = inter / (iarea + areas[j] - inter) # <<<<<<<<<<<<<< + * if ovr >= thresh: + * suppressed[j] = 1 + */ + __pyx_t_17 = __pyx_v_j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_areas.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_areas.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 67, __pyx_L1_error) + } + __pyx_t_24 = ((__pyx_v_iarea + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_areas.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_areas.diminfo[0].strides))) - __pyx_v_inter); + if (unlikely(__pyx_t_24 == 0)) { + PyErr_SetString(PyExc_ZeroDivisionError, "float division"); + __PYX_ERR(0, 67, __pyx_L1_error) + } + __pyx_v_ovr = (__pyx_v_inter / __pyx_t_24); + + /* "cpu_nms.pyx":68 + * inter = w * h + * ovr = inter / (iarea + areas[j] - inter) + * if ovr >= thresh: # <<<<<<<<<<<<<< + * suppressed[j] = 1 + * + */ + __pyx_t_12 = PyFloat_FromDouble(__pyx_v_ovr); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_12); + __pyx_t_1 = PyObject_RichCompare(__pyx_t_12, __pyx_v_thresh, Py_GE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0; + __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_19 < 0)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_19) { + + /* "cpu_nms.pyx":69 + * ovr = inter / (iarea + areas[j] - inter) + * if ovr >= thresh: + * suppressed[j] = 1 # <<<<<<<<<<<<<< + * + * return keep + */ + __pyx_t_17 = __pyx_v_j; + __pyx_t_23 = -1; + if (__pyx_t_17 < 0) { + __pyx_t_17 += __pyx_pybuffernd_suppressed.diminfo[0].shape; + if (unlikely(__pyx_t_17 < 0)) __pyx_t_23 = 0; + } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_suppressed.diminfo[0].shape)) __pyx_t_23 = 0; + if (unlikely(__pyx_t_23 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_23); + __PYX_ERR(0, 69, __pyx_L1_error) + } + *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int_t *, __pyx_pybuffernd_suppressed.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_suppressed.diminfo[0].strides) = 1; + + /* "cpu_nms.pyx":68 + * inter = w * h + * ovr = inter / (iarea + areas[j] - inter) + * if ovr >= thresh: # <<<<<<<<<<<<<< + * suppressed[j] = 1 + * + */ + } + __pyx_L6_continue:; + } + __pyx_L3_continue:; + } + + /* "cpu_nms.pyx":71 + * suppressed[j] = 1 + * + * return keep # <<<<<<<<<<<<<< + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_keep); + __pyx_r = __pyx_v_keep; + goto __pyx_L0; + + /* "cpu_nms.pyx":20 + * return a if a <= b else b + * + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_XDECREF(__pyx_t_12); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_areas.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dets.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_order.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_scores.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_suppressed.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_x1.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_x2.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_y1.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_y2.rcbuffer->pybuffer); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("cpu_nms.cpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_areas.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dets.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_order.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_scores.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_suppressed.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_x1.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_x2.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_y1.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_y2.rcbuffer->pybuffer); + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_x1); + __Pyx_XDECREF((PyObject *)__pyx_v_y1); + __Pyx_XDECREF((PyObject *)__pyx_v_x2); + __Pyx_XDECREF((PyObject *)__pyx_v_y2); + __Pyx_XDECREF((PyObject *)__pyx_v_scores); + __Pyx_XDECREF((PyObject *)__pyx_v_areas); + __Pyx_XDECREF((PyObject *)__pyx_v_order); + __Pyx_XDECREF((PyObject *)__pyx_v_suppressed); + __Pyx_XDECREF(__pyx_v_keep); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":735 + * ctypedef npy_cdouble complex_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":736 + * + * cdef inline object PyArray_MultiIterNew1(a): + * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew2(a, b): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 736, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":735 + * ctypedef npy_cdouble complex_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":738 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":739 + * + * cdef inline object PyArray_MultiIterNew2(a, b): + * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 739, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":738 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":741 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":742 + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): + * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 742, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":741 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":744 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":745 + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): + * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 745, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":744 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":747 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":748 + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 748, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":747 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":750 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":751 + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< + * return d.subarray.shape + * else: + */ + __pyx_t_1 = (PyDataType_HASSUBARRAY(__pyx_v_d) != 0); + if (__pyx_t_1) { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":752 + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape # <<<<<<<<<<<<<< + * else: + * return () + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape)); + __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":751 + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< + * return d.subarray.shape + * else: + */ + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":754 + * return d.subarray.shape + * else: + * return () # <<<<<<<<<<<<<< + * + * + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_empty_tuple); + __pyx_r = __pyx_empty_tuple; + goto __pyx_L0; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":750 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":929 + * int _import_umath() except -1 + * + * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) + */ + +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("set_array_base", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":930 + * + * cdef inline void set_array_base(ndarray arr, object base): + * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< + * PyArray_SetBaseObject(arr, base) + * + */ + Py_INCREF(__pyx_v_base); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":931 + * cdef inline void set_array_base(ndarray arr, object base): + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< + * + * cdef inline object get_array_base(ndarray arr): + */ + (void)(PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base)); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":929 + * int _import_umath() except -1 + * + * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) + */ + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":933 + * PyArray_SetBaseObject(arr, base) + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * base = PyArray_BASE(arr) + * if base is NULL: + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { + PyObject *__pyx_v_base; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + __Pyx_RefNannySetupContext("get_array_base", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":934 + * + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< + * if base is NULL: + * return None + */ + __pyx_v_base = PyArray_BASE(__pyx_v_arr); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":935 + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) + * if base is NULL: # <<<<<<<<<<<<<< + * return None + * return base + */ + __pyx_t_1 = ((__pyx_v_base == NULL) != 0); + if (__pyx_t_1) { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":936 + * base = PyArray_BASE(arr) + * if base is NULL: + * return None # <<<<<<<<<<<<<< + * return base + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":935 + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) + * if base is NULL: # <<<<<<<<<<<<<< + * return None + * return base + */ + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":937 + * if base is NULL: + * return None + * return base # <<<<<<<<<<<<<< + * + * # Versions of the import_* functions which are more suitable for + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_base)); + __pyx_r = ((PyObject *)__pyx_v_base); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":933 + * PyArray_SetBaseObject(arr, base) + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * base = PyArray_BASE(arr) + * if base is NULL: + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":941 + * # Versions of the import_* functions which are more suitable for + * # Cython code. + * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< + * try: + * __pyx_import_array() + */ + +static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_array", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":942 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":943 + * cdef inline int import_array() except -1: + * try: + * __pyx_import_array() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy.core.multiarray failed to import") + */ + __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 943, __pyx_L3_error) + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":942 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":944 + * try: + * __pyx_import_array() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy.core.multiarray failed to import") + * + */ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 944, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":945 + * __pyx_import_array() + * except Exception: + * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_umath() except -1: + */ + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 945, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(1, 945, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":942 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":941 + * # Versions of the import_* functions which are more suitable for + * # Cython code. + * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< + * try: + * __pyx_import_array() + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":947 + * raise ImportError("numpy.core.multiarray failed to import") + * + * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + +static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_umath", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":948 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":949 + * cdef inline int import_umath() except -1: + * try: + * _import_umath() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy.core.umath failed to import") + */ + __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 949, __pyx_L3_error) + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":948 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":950 + * try: + * _import_umath() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy.core.umath failed to import") + * + */ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 950, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":951 + * _import_umath() + * except Exception: + * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_ufunc() except -1: + */ + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 951, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(1, 951, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":948 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":947 + * raise ImportError("numpy.core.multiarray failed to import") + * + * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":953 + * raise ImportError("numpy.core.umath failed to import") + * + * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + +static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_ufunc", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":954 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":955 + * cdef inline int import_ufunc() except -1: + * try: + * _import_umath() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy.core.umath failed to import") + */ + __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 955, __pyx_L3_error) + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":954 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":956 + * try: + * _import_umath() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy.core.umath failed to import") + * + */ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 956, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":957 + * _import_umath() + * except Exception: + * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< + * + * cdef extern from *: + */ + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 957, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(1, 957, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":954 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":953 + * raise ImportError("numpy.core.umath failed to import") + * + * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":967 + * + * + * cdef inline bint is_timedelta64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.timedelta64)` + */ + +static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_obj) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("is_timedelta64_object", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":979 + * bool + * """ + * return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type) # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyTimedeltaArrType_Type)); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":967 + * + * + * cdef inline bint is_timedelta64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.timedelta64)` + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":982 + * + * + * cdef inline bint is_datetime64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.datetime64)` + */ + +static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_obj) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("is_datetime64_object", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":994 + * bool + * """ + * return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type) # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyDatetimeArrType_Type)); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":982 + * + * + * cdef inline bint is_datetime64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.datetime64)` + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":997 + * + * + * cdef inline npy_datetime get_datetime64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy datetime64 object + */ + +static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject *__pyx_v_obj) { + npy_datetime __pyx_r; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1004 + * also needed. That can be found using `get_datetime64_unit`. + * """ + * return (obj).obval # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = ((PyDatetimeScalarObject *)__pyx_v_obj)->obval; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":997 + * + * + * cdef inline npy_datetime get_datetime64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy datetime64 object + */ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1007 + * + * + * cdef inline npy_timedelta get_timedelta64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy timedelta64 object + */ + +static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject *__pyx_v_obj) { + npy_timedelta __pyx_r; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1011 + * returns the int64 value underlying scalar numpy timedelta64 object + * """ + * return (obj).obval # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = ((PyTimedeltaScalarObject *)__pyx_v_obj)->obval; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1007 + * + * + * cdef inline npy_timedelta get_timedelta64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy timedelta64 object + */ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1014 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. + */ + +static CYTHON_INLINE NPY_DATETIMEUNIT __pyx_f_5numpy_get_datetime64_unit(PyObject *__pyx_v_obj) { + NPY_DATETIMEUNIT __pyx_r; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1018 + * returns the unit part of the dtype for a numpy datetime64 object. + * """ + * return (obj).obmeta.base # <<<<<<<<<<<<<< + */ + __pyx_r = ((NPY_DATETIMEUNIT)((PyDatetimeScalarObject *)__pyx_v_obj)->obmeta.base); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1014 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. + */ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_cpu_nms(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_cpu_nms}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "cpu_nms", + 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, + {&__pyx_n_s_areas, __pyx_k_areas, sizeof(__pyx_k_areas), 0, 0, 1, 1}, + {&__pyx_n_s_argsort, __pyx_k_argsort, sizeof(__pyx_k_argsort), 0, 0, 1, 1}, + {&__pyx_n_s_astype, __pyx_k_astype, sizeof(__pyx_k_astype), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_cpu_nms, __pyx_k_cpu_nms, sizeof(__pyx_k_cpu_nms), 0, 0, 1, 1}, + {&__pyx_kp_s_cpu_nms_pyx, __pyx_k_cpu_nms_pyx, sizeof(__pyx_k_cpu_nms_pyx), 0, 0, 1, 0}, + {&__pyx_n_s_dets, __pyx_k_dets, sizeof(__pyx_k_dets), 0, 0, 1, 1}, + {&__pyx_n_s_dtype, __pyx_k_dtype, sizeof(__pyx_k_dtype), 0, 0, 1, 1}, + {&__pyx_n_s_h, __pyx_k_h, sizeof(__pyx_k_h), 0, 0, 1, 1}, + {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, + {&__pyx_n_s_i_2, __pyx_k_i_2, sizeof(__pyx_k_i_2), 0, 0, 1, 1}, + {&__pyx_n_s_iarea, __pyx_k_iarea, sizeof(__pyx_k_iarea), 0, 0, 1, 1}, + {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, + {&__pyx_n_s_int, __pyx_k_int, sizeof(__pyx_k_int), 0, 0, 1, 1}, + {&__pyx_n_s_inter, __pyx_k_inter, sizeof(__pyx_k_inter), 0, 0, 1, 1}, + {&__pyx_n_s_ix1, __pyx_k_ix1, sizeof(__pyx_k_ix1), 0, 0, 1, 1}, + {&__pyx_n_s_ix2, __pyx_k_ix2, sizeof(__pyx_k_ix2), 0, 0, 1, 1}, + {&__pyx_n_s_iy1, __pyx_k_iy1, sizeof(__pyx_k_iy1), 0, 0, 1, 1}, + {&__pyx_n_s_iy2, __pyx_k_iy2, sizeof(__pyx_k_iy2), 0, 0, 1, 1}, + {&__pyx_n_s_j, __pyx_k_j, sizeof(__pyx_k_j), 0, 0, 1, 1}, + {&__pyx_n_s_j_2, __pyx_k_j_2, sizeof(__pyx_k_j_2), 0, 0, 1, 1}, + {&__pyx_n_s_keep, __pyx_k_keep, sizeof(__pyx_k_keep), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_ndets, __pyx_k_ndets, sizeof(__pyx_k_ndets), 0, 0, 1, 1}, + {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, + {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, + {&__pyx_kp_s_numpy_core_multiarray_failed_to, __pyx_k_numpy_core_multiarray_failed_to, sizeof(__pyx_k_numpy_core_multiarray_failed_to), 0, 0, 1, 0}, + {&__pyx_kp_s_numpy_core_umath_failed_to_impor, __pyx_k_numpy_core_umath_failed_to_impor, sizeof(__pyx_k_numpy_core_umath_failed_to_impor), 0, 0, 1, 0}, + {&__pyx_n_s_order, __pyx_k_order, sizeof(__pyx_k_order), 0, 0, 1, 1}, + {&__pyx_n_s_ovr, __pyx_k_ovr, sizeof(__pyx_k_ovr), 0, 0, 1, 1}, + {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, + {&__pyx_n_s_scores, __pyx_k_scores, sizeof(__pyx_k_scores), 0, 0, 1, 1}, + {&__pyx_n_s_suppressed, __pyx_k_suppressed, sizeof(__pyx_k_suppressed), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_thresh, __pyx_k_thresh, sizeof(__pyx_k_thresh), 0, 0, 1, 1}, + {&__pyx_n_s_w, __pyx_k_w, sizeof(__pyx_k_w), 0, 0, 1, 1}, + {&__pyx_n_s_x1, __pyx_k_x1, sizeof(__pyx_k_x1), 0, 0, 1, 1}, + {&__pyx_n_s_x2, __pyx_k_x2, sizeof(__pyx_k_x2), 0, 0, 1, 1}, + {&__pyx_n_s_xx1, __pyx_k_xx1, sizeof(__pyx_k_xx1), 0, 0, 1, 1}, + {&__pyx_n_s_xx2, __pyx_k_xx2, sizeof(__pyx_k_xx2), 0, 0, 1, 1}, + {&__pyx_n_s_y1, __pyx_k_y1, sizeof(__pyx_k_y1), 0, 0, 1, 1}, + {&__pyx_n_s_y2, __pyx_k_y2, sizeof(__pyx_k_y2), 0, 0, 1, 1}, + {&__pyx_n_s_yy1, __pyx_k_yy1, sizeof(__pyx_k_yy1), 0, 0, 1, 1}, + {&__pyx_n_s_yy2, __pyx_k_yy2, sizeof(__pyx_k_yy2), 0, 0, 1, 1}, + {&__pyx_n_s_zeros, __pyx_k_zeros, sizeof(__pyx_k_zeros), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 46, __pyx_L1_error) + __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(1, 945, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "cpu_nms.pyx":21 + * + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + */ + __pyx_slice_ = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice_)) __PYX_ERR(0, 21, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice_); + __Pyx_GIVEREF(__pyx_slice_); + __pyx_tuple__2 = PyTuple_Pack(2, __pyx_slice_, __pyx_int_0); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 21, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__2); + __Pyx_GIVEREF(__pyx_tuple__2); + + /* "cpu_nms.pyx":22 + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] + */ + __pyx_tuple__3 = PyTuple_Pack(2, __pyx_slice_, __pyx_int_1); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__3); + __Pyx_GIVEREF(__pyx_tuple__3); + + /* "cpu_nms.pyx":23 + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] + * cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] + */ + __pyx_tuple__4 = PyTuple_Pack(2, __pyx_slice_, __pyx_int_2); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 23, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__4); + __Pyx_GIVEREF(__pyx_tuple__4); + + /* "cpu_nms.pyx":24 + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] + * + */ + __pyx_tuple__5 = PyTuple_Pack(2, __pyx_slice_, __pyx_int_3); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__5); + __Pyx_GIVEREF(__pyx_tuple__5); + + /* "cpu_nms.pyx":25 + * cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + * cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] + * cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] # <<<<<<<<<<<<<< + * + * cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1) + */ + __pyx_tuple__6 = PyTuple_Pack(2, __pyx_slice_, __pyx_int_4); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__6); + __Pyx_GIVEREF(__pyx_tuple__6); + + /* "cpu_nms.pyx":28 + * + * cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1) + * cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1].astype('i') # <<<<<<<<<<<<<< + * + * cdef int ndets = dets.shape[0] + */ + __pyx_slice__7 = PySlice_New(Py_None, Py_None, __pyx_int_neg_1); if (unlikely(!__pyx_slice__7)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__7); + __Pyx_GIVEREF(__pyx_slice__7); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":945 + * __pyx_import_array() + * except Exception: + * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_umath() except -1: + */ + __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_s_numpy_core_multiarray_failed_to); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 945, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__8); + __Pyx_GIVEREF(__pyx_tuple__8); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":951 + * _import_umath() + * except Exception: + * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_ufunc() except -1: + */ + __pyx_tuple__9 = PyTuple_Pack(1, __pyx_kp_s_numpy_core_umath_failed_to_impor); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 951, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__9); + __Pyx_GIVEREF(__pyx_tuple__9); + + /* "cpu_nms.pyx":20 + * return a if a <= b else b + * + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + */ + __pyx_tuple__10 = PyTuple_Pack(29, __pyx_n_s_dets, __pyx_n_s_thresh, __pyx_n_s_x1, __pyx_n_s_y1, __pyx_n_s_x2, __pyx_n_s_y2, __pyx_n_s_scores, __pyx_n_s_areas, __pyx_n_s_order, __pyx_n_s_ndets, __pyx_n_s_suppressed, __pyx_n_s_i_2, __pyx_n_s_j, __pyx_n_s_i, __pyx_n_s_j_2, __pyx_n_s_ix1, __pyx_n_s_iy1, __pyx_n_s_ix2, __pyx_n_s_iy2, __pyx_n_s_iarea, __pyx_n_s_xx1, __pyx_n_s_yy1, __pyx_n_s_xx2, __pyx_n_s_yy2, __pyx_n_s_w, __pyx_n_s_h, __pyx_n_s_inter, __pyx_n_s_ovr, __pyx_n_s_keep); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(0, 20, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__10); + __Pyx_GIVEREF(__pyx_tuple__10); + __pyx_codeobj__11 = (PyObject*)__Pyx_PyCode_New(2, 0, 29, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__10, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_cpu_nms_pyx, __pyx_n_s_cpu_nms, 20, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__11)) __PYX_ERR(0, 20, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_3 = PyInt_FromLong(3); if (unlikely(!__pyx_int_3)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_4 = PyInt_FromLong(4); if (unlikely(!__pyx_int_4)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 200, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_5numpy_dtype = __Pyx_ImportType(__pyx_t_1, "numpy", "dtype", sizeof(PyArray_Descr), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 200, __pyx_L1_error) + __pyx_ptype_5numpy_flatiter = __Pyx_ImportType(__pyx_t_1, "numpy", "flatiter", sizeof(PyArrayIterObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 223, __pyx_L1_error) + __pyx_ptype_5numpy_broadcast = __Pyx_ImportType(__pyx_t_1, "numpy", "broadcast", sizeof(PyArrayMultiIterObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 227, __pyx_L1_error) + __pyx_ptype_5numpy_ndarray = __Pyx_ImportType(__pyx_t_1, "numpy", "ndarray", sizeof(PyArrayObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 239, __pyx_L1_error) + __pyx_ptype_5numpy_generic = __Pyx_ImportType(__pyx_t_1, "numpy", "generic", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_generic) __PYX_ERR(1, 771, __pyx_L1_error) + __pyx_ptype_5numpy_number = __Pyx_ImportType(__pyx_t_1, "numpy", "number", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_number) __PYX_ERR(1, 773, __pyx_L1_error) + __pyx_ptype_5numpy_integer = __Pyx_ImportType(__pyx_t_1, "numpy", "integer", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_integer) __PYX_ERR(1, 775, __pyx_L1_error) + __pyx_ptype_5numpy_signedinteger = __Pyx_ImportType(__pyx_t_1, "numpy", "signedinteger", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_signedinteger) __PYX_ERR(1, 777, __pyx_L1_error) + __pyx_ptype_5numpy_unsignedinteger = __Pyx_ImportType(__pyx_t_1, "numpy", "unsignedinteger", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_unsignedinteger) __PYX_ERR(1, 779, __pyx_L1_error) + __pyx_ptype_5numpy_inexact = __Pyx_ImportType(__pyx_t_1, "numpy", "inexact", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_inexact) __PYX_ERR(1, 781, __pyx_L1_error) + __pyx_ptype_5numpy_floating = __Pyx_ImportType(__pyx_t_1, "numpy", "floating", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_floating) __PYX_ERR(1, 783, __pyx_L1_error) + __pyx_ptype_5numpy_complexfloating = __Pyx_ImportType(__pyx_t_1, "numpy", "complexfloating", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_complexfloating) __PYX_ERR(1, 785, __pyx_L1_error) + __pyx_ptype_5numpy_flexible = __Pyx_ImportType(__pyx_t_1, "numpy", "flexible", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_flexible) __PYX_ERR(1, 787, __pyx_L1_error) + __pyx_ptype_5numpy_character = __Pyx_ImportType(__pyx_t_1, "numpy", "character", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_character) __PYX_ERR(1, 789, __pyx_L1_error) + __pyx_ptype_5numpy_ufunc = __Pyx_ImportType(__pyx_t_1, "numpy", "ufunc", sizeof(PyUFuncObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 827, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#ifndef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#elif PY_MAJOR_VERSION < 3 +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" void +#else +#define __Pyx_PyMODINIT_FUNC void +#endif +#else +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyObject * +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initcpu_nms(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initcpu_nms(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_cpu_nms(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_cpu_nms(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_cpu_nms(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'cpu_nms' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_cpu_nms(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + PyEval_InitThreads(); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("cpu_nms", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main_cpu_nms) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "cpu_nms")) { + if (unlikely(PyDict_SetItemString(modules, "cpu_nms", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + (void)__Pyx_modinit_type_init_code(); + if (unlikely(__Pyx_modinit_type_import_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "cpu_nms.pyx":11 + * from __future__ import print_function + * + * import numpy as np # <<<<<<<<<<<<<< + * cimport numpy as np + * + */ + __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "cpu_nms.pyx":20 + * return a if a <= b else b + * + * def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + * cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7cpu_nms_1cpu_nms, NULL, __pyx_n_s_cpu_nms); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 20, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_cpu_nms, __pyx_t_1) < 0) __PYX_ERR(0, 20, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "cpu_nms.pyx":1 + * # ------------------------------------------------------------------------------ # <<<<<<<<<<<<<< + * # Copyright (c) Microsoft + * # Licensed under the MIT License. + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1014 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. + */ + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init cpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init cpu_nms"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* ArgTypeTest */ +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) +{ + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + else if (exact) { + #if PY_MAJOR_VERSION == 2 + if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; + #endif + } + else { + if (likely(__Pyx_TypeCheck(obj, type))) return 1; + } + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); + return 0; +} + +/* IsLittleEndian */ +static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) +{ + union { + uint32_t u32; + uint8_t u8[4]; + } S; + S.u32 = 0x01020304; + return S.u8[0] == 4; +} + +/* BufferFormatCheck */ +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type) { + stack[0].field = &ctx->root; + stack[0].parent_offset = 0; + ctx->root.type = type; + ctx->root.name = "buffer dtype"; + ctx->root.offset = 0; + ctx->head = stack; + ctx->head->field = &ctx->root; + ctx->fmt_offset = 0; + ctx->head->parent_offset = 0; + ctx->new_packmode = '@'; + ctx->enc_packmode = '@'; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->is_complex = 0; + ctx->is_valid_array = 0; + ctx->struct_alignment = 0; + while (type->typegroup == 'S') { + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = 0; + type = type->fields->type; + } +} +static int __Pyx_BufFmt_ParseNumber(const char** ts) { + int count; + const char* t = *ts; + if (*t < '0' || *t > '9') { + return -1; + } else { + count = *t++ - '0'; + while (*t >= '0' && *t <= '9') { + count *= 10; + count += *t++ - '0'; + } + } + *ts = t; + return count; +} +static int __Pyx_BufFmt_ExpectNumber(const char **ts) { + int number = __Pyx_BufFmt_ParseNumber(ts); + if (number == -1) + PyErr_Format(PyExc_ValueError,\ + "Does not understand character buffer dtype format string ('%c')", **ts); + return number; +} +static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { + PyErr_Format(PyExc_ValueError, + "Unexpected format string character: '%c'", ch); +} +static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { + switch (ch) { + case '?': return "'bool'"; + case 'c': return "'char'"; + case 'b': return "'signed char'"; + case 'B': return "'unsigned char'"; + case 'h': return "'short'"; + case 'H': return "'unsigned short'"; + case 'i': return "'int'"; + case 'I': return "'unsigned int'"; + case 'l': return "'long'"; + case 'L': return "'unsigned long'"; + case 'q': return "'long long'"; + case 'Q': return "'unsigned long long'"; + case 'f': return (is_complex ? "'complex float'" : "'float'"); + case 'd': return (is_complex ? "'complex double'" : "'double'"); + case 'g': return (is_complex ? "'complex long double'" : "'long double'"); + case 'T': return "a struct"; + case 'O': return "Python object"; + case 'P': return "a pointer"; + case 's': case 'p': return "a string"; + case 0: return "end"; + default: return "unparseable format string"; + } +} +static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return 2; + case 'i': case 'I': case 'l': case 'L': return 4; + case 'q': case 'Q': return 8; + case 'f': return (is_complex ? 8 : 4); + case 'd': return (is_complex ? 16 : 8); + case 'g': { + PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); + return 0; + } + case 'O': case 'P': return sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(short); + case 'i': case 'I': return sizeof(int); + case 'l': case 'L': return sizeof(long); + #ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(PY_LONG_LONG); + #endif + case 'f': return sizeof(float) * (is_complex ? 2 : 1); + case 'd': return sizeof(double) * (is_complex ? 2 : 1); + case 'g': return sizeof(long double) * (is_complex ? 2 : 1); + case 'O': case 'P': return sizeof(void*); + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +typedef struct { char c; short x; } __Pyx_st_short; +typedef struct { char c; int x; } __Pyx_st_int; +typedef struct { char c; long x; } __Pyx_st_long; +typedef struct { char c; float x; } __Pyx_st_float; +typedef struct { char c; double x; } __Pyx_st_double; +typedef struct { char c; long double x; } __Pyx_st_longdouble; +typedef struct { char c; void *x; } __Pyx_st_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; +#endif +static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_st_float) - sizeof(float); + case 'd': return sizeof(__Pyx_st_double) - sizeof(double); + case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +/* These are for computing the padding at the end of the struct to align + on the first member of the struct. This will probably the same as above, + but we don't have any guarantees. + */ +typedef struct { short x; char c; } __Pyx_pad_short; +typedef struct { int x; char c; } __Pyx_pad_int; +typedef struct { long x; char c; } __Pyx_pad_long; +typedef struct { float x; char c; } __Pyx_pad_float; +typedef struct { double x; char c; } __Pyx_pad_double; +typedef struct { long double x; char c; } __Pyx_pad_longdouble; +typedef struct { void *x; char c; } __Pyx_pad_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; +#endif +static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); + case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); + case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { + switch (ch) { + case 'c': + return 'H'; + case 'b': case 'h': case 'i': + case 'l': case 'q': case 's': case 'p': + return 'I'; + case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': + return 'U'; + case 'f': case 'd': case 'g': + return (is_complex ? 'C' : 'R'); + case 'O': + return 'O'; + case 'P': + return 'P'; + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { + if (ctx->head == NULL || ctx->head->field == &ctx->root) { + const char* expected; + const char* quote; + if (ctx->head == NULL) { + expected = "end"; + quote = ""; + } else { + expected = ctx->head->field->type->name; + quote = "'"; + } + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected %s%s%s but got %s", + quote, expected, quote, + __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); + } else { + __Pyx_StructField* field = ctx->head->field; + __Pyx_StructField* parent = (ctx->head - 1)->field; + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", + field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), + parent->type->name, field->name); + } +} +static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { + char group; + size_t size, offset, arraysize = 1; + if (ctx->enc_type == 0) return 0; + if (ctx->head->field->type->arraysize[0]) { + int i, ndim = 0; + if (ctx->enc_type == 's' || ctx->enc_type == 'p') { + ctx->is_valid_array = ctx->head->field->type->ndim == 1; + ndim = 1; + if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { + PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %zu", + ctx->head->field->type->arraysize[0], ctx->enc_count); + return -1; + } + } + if (!ctx->is_valid_array) { + PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", + ctx->head->field->type->ndim, ndim); + return -1; + } + for (i = 0; i < ctx->head->field->type->ndim; i++) { + arraysize *= ctx->head->field->type->arraysize[i]; + } + ctx->is_valid_array = 0; + ctx->enc_count = 1; + } + group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); + do { + __Pyx_StructField* field = ctx->head->field; + __Pyx_TypeInfo* type = field->type; + if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { + size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); + } else { + size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); + } + if (ctx->enc_packmode == '@') { + size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); + size_t align_mod_offset; + if (align_at == 0) return -1; + align_mod_offset = ctx->fmt_offset % align_at; + if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; + if (ctx->struct_alignment == 0) + ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, + ctx->is_complex); + } + if (type->size != size || type->typegroup != group) { + if (type->typegroup == 'C' && type->fields != NULL) { + size_t parent_offset = ctx->head->parent_offset + field->offset; + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = parent_offset; + continue; + } + if ((type->typegroup == 'H' || group == 'H') && type->size == size) { + } else { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + } + offset = ctx->head->parent_offset + field->offset; + if (ctx->fmt_offset != offset) { + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", + (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); + return -1; + } + ctx->fmt_offset += size; + if (arraysize) + ctx->fmt_offset += (arraysize - 1) * size; + --ctx->enc_count; + while (1) { + if (field == &ctx->root) { + ctx->head = NULL; + if (ctx->enc_count != 0) { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + break; + } + ctx->head->field = ++field; + if (field->type == NULL) { + --ctx->head; + field = ctx->head->field; + continue; + } else if (field->type->typegroup == 'S') { + size_t parent_offset = ctx->head->parent_offset + field->offset; + if (field->type->fields->type == NULL) continue; + field = field->type->fields; + ++ctx->head; + ctx->head->field = field; + ctx->head->parent_offset = parent_offset; + break; + } else { + break; + } + } + } while (ctx->enc_count); + ctx->enc_type = 0; + ctx->is_complex = 0; + return 0; +} +static PyObject * +__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) +{ + const char *ts = *tsp; + int i = 0, number, ndim; + ++ts; + if (ctx->new_count != 1) { + PyErr_SetString(PyExc_ValueError, + "Cannot handle repeated arrays in format string"); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ndim = ctx->head->field->type->ndim; + while (*ts && *ts != ')') { + switch (*ts) { + case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; + default: break; + } + number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return NULL; + if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) + return PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %d", + ctx->head->field->type->arraysize[i], number); + if (*ts != ',' && *ts != ')') + return PyErr_Format(PyExc_ValueError, + "Expected a comma in format string, got '%c'", *ts); + if (*ts == ',') ts++; + i++; + } + if (i != ndim) + return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", + ctx->head->field->type->ndim, i); + if (!*ts) { + PyErr_SetString(PyExc_ValueError, + "Unexpected end of format string, expected ')'"); + return NULL; + } + ctx->is_valid_array = 1; + ctx->new_count = 1; + *tsp = ++ts; + return Py_None; +} +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { + int got_Z = 0; + while (1) { + switch(*ts) { + case 0: + if (ctx->enc_type != 0 && ctx->head == NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + if (ctx->head != NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + return ts; + case ' ': + case '\r': + case '\n': + ++ts; + break; + case '<': + if (!__Pyx_Is_Little_Endian()) { + PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '>': + case '!': + if (__Pyx_Is_Little_Endian()) { + PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '=': + case '@': + case '^': + ctx->new_packmode = *ts++; + break; + case 'T': + { + const char* ts_after_sub; + size_t i, struct_count = ctx->new_count; + size_t struct_alignment = ctx->struct_alignment; + ctx->new_count = 1; + ++ts; + if (*ts != '{') { + PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + ctx->enc_count = 0; + ctx->struct_alignment = 0; + ++ts; + ts_after_sub = ts; + for (i = 0; i != struct_count; ++i) { + ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); + if (!ts_after_sub) return NULL; + } + ts = ts_after_sub; + if (struct_alignment) ctx->struct_alignment = struct_alignment; + } + break; + case '}': + { + size_t alignment = ctx->struct_alignment; + ++ts; + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + if (alignment && ctx->fmt_offset % alignment) { + ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); + } + } + return ts; + case 'x': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->fmt_offset += ctx->new_count; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->enc_packmode = ctx->new_packmode; + ++ts; + break; + case 'Z': + got_Z = 1; + ++ts; + if (*ts != 'f' && *ts != 'd' && *ts != 'g') { + __Pyx_BufFmt_RaiseUnexpectedChar('Z'); + return NULL; + } + CYTHON_FALLTHROUGH; + case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': + case 'l': case 'L': case 'q': case 'Q': + case 'f': case 'd': case 'g': + case 'O': case 'p': + if ((ctx->enc_type == *ts) && (got_Z == ctx->is_complex) && + (ctx->enc_packmode == ctx->new_packmode) && (!ctx->is_valid_array)) { + ctx->enc_count += ctx->new_count; + ctx->new_count = 1; + got_Z = 0; + ++ts; + break; + } + CYTHON_FALLTHROUGH; + case 's': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_count = ctx->new_count; + ctx->enc_packmode = ctx->new_packmode; + ctx->enc_type = *ts; + ctx->is_complex = got_Z; + ++ts; + ctx->new_count = 1; + got_Z = 0; + break; + case ':': + ++ts; + while(*ts != ':') ++ts; + ++ts; + break; + case '(': + if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL; + break; + default: + { + int number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return NULL; + ctx->new_count = (size_t)number; + } + } + } +} + +/* BufferGetAndValidate */ + static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { + if (unlikely(info->buf == NULL)) return; + if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; + __Pyx_ReleaseBuffer(info); +} +static void __Pyx_ZeroBuffer(Py_buffer* buf) { + buf->buf = NULL; + buf->obj = NULL; + buf->strides = __Pyx_zeros; + buf->shape = __Pyx_zeros; + buf->suboffsets = __Pyx_minusones; +} +static int __Pyx__GetBufferAndValidate( + Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, + int nd, int cast, __Pyx_BufFmt_StackElem* stack) +{ + buf->buf = NULL; + if (unlikely(__Pyx_GetBuffer(obj, buf, flags) == -1)) { + __Pyx_ZeroBuffer(buf); + return -1; + } + if (unlikely(buf->ndim != nd)) { + PyErr_Format(PyExc_ValueError, + "Buffer has wrong number of dimensions (expected %d, got %d)", + nd, buf->ndim); + goto fail; + } + if (!cast) { + __Pyx_BufFmt_Context ctx; + __Pyx_BufFmt_Init(&ctx, stack, dtype); + if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; + } + if (unlikely((size_t)buf->itemsize != dtype->size)) { + PyErr_Format(PyExc_ValueError, + "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", + buf->itemsize, (buf->itemsize > 1) ? "s" : "", + dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); + goto fail; + } + if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; + return 0; +fail:; + __Pyx_SafeReleaseBuffer(buf); + return -1; +} + +/* GetItemInt */ + static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyList_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyTuple_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); + if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { + PyObject *r = PyList_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } + else if (PyTuple_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } else { + PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; + if (likely(m && m->sq_item)) { + if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { + Py_ssize_t l = m->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return NULL; + PyErr_Clear(); + } + } + return m->sq_item(o, i); + } + } +#else + if (is_list || PySequence_Check(o)) { + return PySequence_GetItem(o, i); + } +#endif + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +} + +/* ObjectGetItem */ + #if CYTHON_USE_TYPE_SLOTS +static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { + PyObject *runerr; + Py_ssize_t key_value; + PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; + if (unlikely(!(m && m->sq_item))) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); + return NULL; + } + key_value = __Pyx_PyIndex_AsSsize_t(index); + if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { + return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); + } + if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { + PyErr_Clear(); + PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); + } + return NULL; +} +static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { + PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; + if (likely(m && m->mp_subscript)) { + return m->mp_subscript(obj, key); + } + return __Pyx_PyObject_GetIndex(obj, key); +} +#endif + +/* ExtTypeTest */ + static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(__Pyx_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; +} + +/* PyIntBinop */ + #if !CYTHON_COMPILING_IN_PYPY +static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace, int zerodivision_check) { + (void)inplace; + (void)zerodivision_check; + #if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(op1))) { + const long b = intval; + long x; + long a = PyInt_AS_LONG(op1); + x = (long)((unsigned long)a + b); + if (likely((x^a) >= 0 || (x^b) >= 0)) + return PyInt_FromLong(x); + return PyLong_Type.tp_as_number->nb_add(op1, op2); + } + #endif + #if CYTHON_USE_PYLONG_INTERNALS + if (likely(PyLong_CheckExact(op1))) { + const long b = intval; + long a, x; +#ifdef HAVE_LONG_LONG + const PY_LONG_LONG llb = intval; + PY_LONG_LONG lla, llx; +#endif + const digit* digits = ((PyLongObject*)op1)->ob_digit; + const Py_ssize_t size = Py_SIZE(op1); + if (likely(__Pyx_sst_abs(size) <= 1)) { + a = likely(size) ? digits[0] : 0; + if (size == -1) a = -a; + } else { + switch (size) { + case -2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 2: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 3: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case -4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = -(PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + case 4: + if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); + break; +#ifdef HAVE_LONG_LONG + } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { + lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); + goto long_long; +#endif + } + CYTHON_FALLTHROUGH; + default: return PyLong_Type.tp_as_number->nb_add(op1, op2); + } + } + x = a + b; + return PyLong_FromLong(x); +#ifdef HAVE_LONG_LONG + long_long: + llx = lla + llb; + return PyLong_FromLongLong(llx); +#endif + + + } + #endif + if (PyFloat_CheckExact(op1)) { + const long b = intval; + double a = PyFloat_AS_DOUBLE(op1); + double result; + PyFPE_START_PROTECT("add", return NULL) + result = ((double)a) + (double)b; + PyFPE_END_PROTECT(result) + return PyFloat_FromDouble(result); + } + return (inplace ? PyNumber_InPlaceAdd : PyNumber_Add)(op1, op2); +} +#endif + +/* PyFunctionFastCall */ + #if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyObjectCall */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = Py_TYPE(func)->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallNoArg */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, NULL, 0); + } +#endif +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) +#else + if (likely(PyCFunction_Check(func))) +#endif + { + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + +/* PyCFunctionFastCall */ + #if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyObjectCallOneArg */ + #if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (__Pyx_PyFastCFunction_Check(func)) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyObjectCall2Args */ + static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { + PyObject *args, *result = NULL; + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyFunction_FastCall(function, args, 2); + } + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyCFunction_FastCall(function, args, 2); + } + #endif + args = PyTuple_New(2); + if (unlikely(!args)) goto done; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + Py_INCREF(function); + result = __Pyx_PyObject_Call(function, args, NULL); + Py_DECREF(args); + Py_DECREF(function); +done: + return result; +} + +/* PyDictVersioning */ + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ + #if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* BufferIndexError */ + static void __Pyx_RaiseBufferIndexError(int axis) { + PyErr_Format(PyExc_IndexError, + "Out of bounds on buffer access (axis %d)", axis); +} + +/* PyErrFetchRestore */ + #if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* GetTopmostException */ + #if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* SaveResetException */ + #if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + *type = exc_info->exc_type; + *value = exc_info->exc_value; + *tb = exc_info->exc_traceback; + #else + *type = tstate->exc_type; + *value = tstate->exc_value; + *tb = tstate->exc_traceback; + #endif + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); +} +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_traceback = tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = type; + tstate->exc_value = value; + tstate->exc_traceback = tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +#endif + +/* PyErrExceptionMatches */ + #if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; icurexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; + if (unlikely(PyTuple_Check(err))) + return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); +} +#endif + +/* GetException */ + #if CYTHON_FAST_THREAD_STATE +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) +#endif +{ + PyObject *local_type, *local_value, *local_tb; +#if CYTHON_FAST_THREAD_STATE + PyObject *tmp_type, *tmp_value, *tmp_tb; + local_type = tstate->curexc_type; + local_value = tstate->curexc_value; + local_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#else + PyErr_Fetch(&local_type, &local_value, &local_tb); +#endif + PyErr_NormalizeException(&local_type, &local_value, &local_tb); +#if CYTHON_FAST_THREAD_STATE + if (unlikely(tstate->curexc_type)) +#else + if (unlikely(PyErr_Occurred())) +#endif + goto bad; + #if PY_MAJOR_VERSION >= 3 + if (local_tb) { + if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) + goto bad; + } + #endif + Py_XINCREF(local_tb); + Py_XINCREF(local_type); + Py_XINCREF(local_value); + *type = local_type; + *value = local_value; + *tb = local_tb; +#if CYTHON_FAST_THREAD_STATE + #if CYTHON_USE_EXC_INFO_STACK + { + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = local_type; + exc_info->exc_value = local_value; + exc_info->exc_traceback = local_tb; + } + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = local_type; + tstate->exc_value = local_value; + tstate->exc_traceback = local_tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#else + PyErr_SetExcInfo(local_type, local_value, local_tb); +#endif + return 0; +bad: + *type = 0; + *value = 0; + *tb = 0; + Py_XDECREF(local_type); + Py_XDECREF(local_value); + Py_XDECREF(local_tb); + return -1; +} + +/* RaiseException */ + #if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, + CYTHON_UNUSED PyObject *cause) { + __Pyx_PyThreadState_declare + Py_XINCREF(type); + if (!value || value == Py_None) + value = NULL; + else + Py_INCREF(value); + if (!tb || tb == Py_None) + tb = NULL; + else { + Py_INCREF(tb); + if (!PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + } + if (PyType_Check(type)) { +#if CYTHON_COMPILING_IN_PYPY + if (!value) { + Py_INCREF(Py_None); + value = Py_None; + } +#endif + PyErr_NormalizeException(&type, &value, &tb); + } else { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + value = type; + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + } + __Pyx_PyThreadState_assign + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} +#else +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if CYTHON_COMPILING_IN_PYPY + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#else + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} +#endif + +/* TypeImport */ + #ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, + size_t size, enum __Pyx_ImportType_CheckSize check_size) +{ + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if ((size_t)basicsize < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* Import */ + static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + #if PY_MAJOR_VERSION < 3 + PyObject *py_import; + py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); + if (!py_import) + goto bad; + #endif + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + { + #if PY_MAJOR_VERSION >= 3 + if (level == -1) { + if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, 1); + if (!module) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + goto bad; + PyErr_Clear(); + } + } + level = 0; + } + #endif + if (!module) { + #if PY_MAJOR_VERSION < 3 + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, level); + #endif + } + } +bad: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_import); + #endif + Py_XDECREF(empty_list); + Py_XDECREF(empty_dict); + return module; +} + +/* CLineInTraceback */ + #ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ + static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ + #include "compile.h" +#include "frameobject.h" +#include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; + py_srcfile = PyString_FromString(filename); + if (!py_srcfile) goto bad; + #endif + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + #endif + } + #if PY_MAJOR_VERSION < 3 + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline + return py_code; +bad: + Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +#if PY_MAJOR_VERSION < 3 +static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { + if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); + PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name); + return -1; +} +static void __Pyx_ReleaseBuffer(Py_buffer *view) { + PyObject *obj = view->obj; + if (!obj) return; + if (PyObject_CheckBuffer(obj)) { + PyBuffer_Release(view); + return; + } + if ((0)) {} + view->obj = NULL; + Py_DECREF(obj); +} +#endif + + + /* CIntFromPyVerify */ + #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* Declarations */ + #if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return ::std::complex< float >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return x + y*(__pyx_t_float_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + __pyx_t_float_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +/* Arithmetic */ + #if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + #if 1 + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + if (b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); + } else if (fabsf(b.real) >= fabsf(b.imag)) { + if (b.real == 0 && b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); + } else { + float r = b.imag / b.real; + float s = (float)(1.0) / (b.real + b.imag * r); + return __pyx_t_float_complex_from_parts( + (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); + } + } else { + float r = b.real / b.imag; + float s = (float)(1.0) / (b.imag + b.real * r); + return __pyx_t_float_complex_from_parts( + (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); + } + } + #else + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + if (b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); + } else { + float denom = b.real * b.real + b.imag * b.imag; + return __pyx_t_float_complex_from_parts( + (a.real * b.real + a.imag * b.imag) / denom, + (a.imag * b.real - a.real * b.imag) / denom); + } + } + #endif + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrtf(z.real*z.real + z.imag*z.imag); + #else + return hypotf(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + float r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + float denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + return __Pyx_c_prod_float(a, a); + case 3: + z = __Pyx_c_prod_float(a, a); + return __Pyx_c_prod_float(z, a); + case 4: + z = __Pyx_c_prod_float(a, a); + return __Pyx_c_prod_float(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } else if (b.imag == 0) { + z.real = powf(a.real, b.real); + z.imag = 0; + return z; + } else if (a.real > 0) { + r = a.real; + theta = 0; + } else { + r = -a.real; + theta = atan2f(0.0, -1.0); + } + } else { + r = __Pyx_c_abs_float(a); + theta = atan2f(a.imag, a.real); + } + lnr = logf(r); + z_r = expf(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cosf(z_theta); + z.imag = z_r * sinf(z_theta); + return z; + } + #endif +#endif + +/* Declarations */ + #if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return ::std::complex< double >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return x + y*(__pyx_t_double_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + __pyx_t_double_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +/* Arithmetic */ + #if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + #if 1 + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + if (b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else if (fabs(b.real) >= fabs(b.imag)) { + if (b.real == 0 && b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); + } else { + double r = b.imag / b.real; + double s = (double)(1.0) / (b.real + b.imag * r); + return __pyx_t_double_complex_from_parts( + (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); + } + } else { + double r = b.real / b.imag; + double s = (double)(1.0) / (b.imag + b.real * r); + return __pyx_t_double_complex_from_parts( + (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); + } + } + #else + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + if (b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else { + double denom = b.real * b.real + b.imag * b.imag; + return __pyx_t_double_complex_from_parts( + (a.real * b.real + a.imag * b.imag) / denom, + (a.imag * b.real - a.real * b.imag) / denom); + } + } + #endif + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrt(z.real*z.real + z.imag*z.imag); + #else + return hypot(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + double r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + double denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + return __Pyx_c_prod_double(a, a); + case 3: + z = __Pyx_c_prod_double(a, a); + return __Pyx_c_prod_double(z, a); + case 4: + z = __Pyx_c_prod_double(a, a); + return __Pyx_c_prod_double(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } else if (b.imag == 0) { + z.real = pow(a.real, b.real); + z.imag = 0; + return z; + } else if (a.real > 0) { + r = a.real; + theta = 0; + } else { + r = -a.real; + theta = atan2(0.0, -1.0); + } + } else { + r = __Pyx_c_abs_double(a); + theta = atan2(a.imag, a.real); + } + lnr = log(r); + z_r = exp(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cos(z_theta); + z.imag = z_r * sin(z_theta); + return z; + } + #endif +#endif + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + } +} + +/* CIntFromPy */ + static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* CIntFromPy */ + static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* FastTypeChecks */ + #if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; i '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; + char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } + PyOS_snprintf(message, sizeof(message), + "compiletime version %s of module '%.100s' " + "does not match runtime version %s", + ctversion, __Pyx_MODULE_NAME, rtversion); + return PyErr_WarnEx(NULL, message, 1); + } + return 0; +} + +/* InitStrings */ + static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/easy_ViTPose/vit_utils/nms/cpu_nms.cpython-37m-x86_64-linux-gnu.so b/easy_ViTPose/vit_utils/nms/cpu_nms.cpython-37m-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..15f053c5364a7aa75f568dac77c74be7b2fc3b24 Binary files /dev/null and b/easy_ViTPose/vit_utils/nms/cpu_nms.cpython-37m-x86_64-linux-gnu.so differ diff --git a/easy_ViTPose/vit_utils/nms/cpu_nms.cpython-39-x86_64-linux-gnu.so b/easy_ViTPose/vit_utils/nms/cpu_nms.cpython-39-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..d9da25778d89e0baab25d1ad350ffe74d8f659bb Binary files /dev/null and b/easy_ViTPose/vit_utils/nms/cpu_nms.cpython-39-x86_64-linux-gnu.so differ diff --git a/easy_ViTPose/vit_utils/nms/cpu_nms.pyx b/easy_ViTPose/vit_utils/nms/cpu_nms.pyx new file mode 100644 index 0000000000000000000000000000000000000000..3cd0d74097da10fbba6d674d8928fdc1feb43a53 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/cpu_nms.pyx @@ -0,0 +1,71 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft +# Licensed under the MIT License. +# Written by Bin Xiao (Bin.Xiao@microsoft.com) +# ------------------------------------------------------------------------------ + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np +cimport numpy as np + +cdef inline np.float32_t max(np.float32_t a, np.float32_t b): + return a if a >= b else b + +cdef inline np.float32_t min(np.float32_t a, np.float32_t b): + return a if a <= b else b + +def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh): + cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0] + cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1] + cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2] + cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3] + cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4] + + cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1) + cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1].astype('i') + + cdef int ndets = dets.shape[0] + cdef np.ndarray[np.int_t, ndim=1] suppressed = \ + np.zeros((ndets), dtype=np.int) + + # nominal indices + cdef int _i, _j + # sorted indices + cdef int i, j + # temp variables for box i's (the box currently under consideration) + cdef np.float32_t ix1, iy1, ix2, iy2, iarea + # variables for computing overlap with box j (lower scoring box) + cdef np.float32_t xx1, yy1, xx2, yy2 + cdef np.float32_t w, h + cdef np.float32_t inter, ovr + + keep = [] + for _i in range(ndets): + i = order[_i] + if suppressed[i] == 1: + continue + keep.append(i) + ix1 = x1[i] + iy1 = y1[i] + ix2 = x2[i] + iy2 = y2[i] + iarea = areas[i] + for _j in range(_i + 1, ndets): + j = order[_j] + if suppressed[j] == 1: + continue + xx1 = max(ix1, x1[j]) + yy1 = max(iy1, y1[j]) + xx2 = min(ix2, x2[j]) + yy2 = min(iy2, y2[j]) + w = max(0.0, xx2 - xx1 + 1) + h = max(0.0, yy2 - yy1 + 1) + inter = w * h + ovr = inter / (iarea + areas[j] - inter) + if ovr >= thresh: + suppressed[j] = 1 + + return keep diff --git a/easy_ViTPose/vit_utils/nms/gpu_nms.cpp b/easy_ViTPose/vit_utils/nms/gpu_nms.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d85dbfbbde9a53b0c8998656947d45cc08fe2b3c --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/gpu_nms.cpp @@ -0,0 +1,7357 @@ +/* Generated by Cython 0.29.32 */ + +#ifndef PY_SSIZE_T_CLEAN +#define PY_SSIZE_T_CLEAN +#endif /* PY_SSIZE_T_CLEAN */ +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_32" +#define CYTHON_HEX_VERSION 0x001D20F0 +#define CYTHON_FUTURE_DIVISION 1 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_HEX >= 0x07030900) + #endif +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 + #endif +#elif defined(PY_NOGIL) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #define CYTHON_COMPILING_IN_NOGIL 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #ifndef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 1 + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 1 + #endif + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #define CYTHON_COMPILING_IN_NOGIL 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #elif !defined(CYTHON_FAST_THREAD_STATE) + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 + #elif !defined(CYTHON_USE_EXC_INFO_STACK) + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif + #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC + #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #if PY_MAJOR_VERSION < 3 + #include "longintrepr.h" + #endif + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef __cplusplus + #error "Cython files generated with the C++ option must be compiled with a C++ compiler." +#endif +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #else + #define CYTHON_INLINE inline + #endif +#endif +template +void __Pyx_call_destructor(T& x) { + x.~T(); +} +template +class __Pyx_FakeReference { + public: + __Pyx_FakeReference() : ptr(NULL) { } + __Pyx_FakeReference(const T& ref) : ptr(const_cast(&ref)) { } + T *operator->() { return ptr; } + T *operator&() { return ptr; } + operator T&() { return *ptr; } + template bool operator ==(U other) { return *ptr == other; } + template bool operator !=(U other) { return *ptr != other; } + private: + T *ptr; +}; + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_DefaultClassType PyType_Type +#if PY_VERSION_HEX >= 0x030B00A1 + static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, + PyObject *code, PyObject *c, PyObject* n, PyObject *v, + PyObject *fv, PyObject *cell, PyObject* fn, + PyObject *name, int fline, PyObject *lnos) { + PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; + PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; + const char *fn_cstr=NULL; + const char *name_cstr=NULL; + PyCodeObject* co=NULL; + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!(kwds=PyDict_New())) goto end; + if (!(argcount=PyLong_FromLong(a))) goto end; + if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; + if (!(posonlyargcount=PyLong_FromLong(0))) goto end; + if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; + if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; + if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; + if (!(nlocals=PyLong_FromLong(l))) goto end; + if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; + if (!(stacksize=PyLong_FromLong(s))) goto end; + if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; + if (!(flags=PyLong_FromLong(f))) goto end; + if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; + if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; + if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; + if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; + if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; + if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; + if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here + if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; + Py_XDECREF((PyObject*)co); + co = (PyCodeObject*)call_result; + call_result = NULL; + if (0) { + cleanup_code_too: + Py_XDECREF((PyObject*)co); + co = NULL; + } + end: + Py_XDECREF(kwds); + Py_XDECREF(argcount); + Py_XDECREF(posonlyargcount); + Py_XDECREF(kwonlyargcount); + Py_XDECREF(nlocals); + Py_XDECREF(stacksize); + Py_XDECREF(replace); + Py_XDECREF(call_result); + Py_XDECREF(empty); + if (type) { + PyErr_Restore(type, value, traceback); + } + return co; + } +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #if defined(PyUnicode_IS_READY) + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #else + #define __Pyx_PyUnicode_READY(op) (0) + #endif + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE) + #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) + #endif + #else + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) + #endif +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#ifndef PyObject_Unicode + #define PyObject_Unicode PyObject_Str +#endif +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) + #if !defined(_USE_MATH_DEFINES) + #define _USE_MATH_DEFINES + #endif +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#define __PYX_MARK_ERR_POS(f_index, lineno) \ + { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__gpu_nms +#define __PYX_HAVE_API__gpu_nms +/* Early includes */ +#include +#include +#include "numpy/arrayobject.h" +#include "numpy/ndarrayobject.h" +#include "numpy/ndarraytypes.h" +#include "numpy/arrayscalars.h" +#include "numpy/ufuncobject.h" + + /* NumPy API declarations from "numpy/__init__.pxd" */ + +#include "gpu_nms.hpp" +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + +/* Header.proto */ +#if !defined(CYTHON_CCOMPLEX) + #if defined(__cplusplus) + #define CYTHON_CCOMPLEX 1 + #elif defined(_Complex_I) + #define CYTHON_CCOMPLEX 1 + #else + #define CYTHON_CCOMPLEX 0 + #endif +#endif +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #include + #else + #include + #endif +#endif +#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) + #undef _Complex_I + #define _Complex_I 1.0fj +#endif + + +static const char *__pyx_f[] = { + "gpu_nms.pyx", + "__init__.pxd", + "type.pxd", +}; +/* BufferFormatStructs.proto */ +#define IS_UNSIGNED(type) (((type) -1) > 0) +struct __Pyx_StructField_; +#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) +typedef struct { + const char* name; + struct __Pyx_StructField_* fields; + size_t size; + size_t arraysize[8]; + int ndim; + char typegroup; + char is_unsigned; + int flags; +} __Pyx_TypeInfo; +typedef struct __Pyx_StructField_ { + __Pyx_TypeInfo* type; + const char* name; + size_t offset; +} __Pyx_StructField; +typedef struct { + __Pyx_StructField* field; + size_t parent_offset; +} __Pyx_BufFmt_StackElem; +typedef struct { + __Pyx_StructField root; + __Pyx_BufFmt_StackElem* head; + size_t fmt_offset; + size_t new_count, enc_count; + size_t struct_alignment; + int is_complex; + char enc_type; + char new_packmode; + char enc_packmode; + char is_valid_array; +} __Pyx_BufFmt_Context; + + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":690 + * # in Cython to enable them only on the right systems. + * + * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t + */ +typedef npy_int8 __pyx_t_5numpy_int8_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":691 + * + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t + */ +typedef npy_int16 __pyx_t_5numpy_int16_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":692 + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< + * ctypedef npy_int64 int64_t + * #ctypedef npy_int96 int96_t + */ +typedef npy_int32 __pyx_t_5numpy_int32_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":693 + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< + * #ctypedef npy_int96 int96_t + * #ctypedef npy_int128 int128_t + */ +typedef npy_int64 __pyx_t_5numpy_int64_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":697 + * #ctypedef npy_int128 int128_t + * + * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t + */ +typedef npy_uint8 __pyx_t_5numpy_uint8_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":698 + * + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t + */ +typedef npy_uint16 __pyx_t_5numpy_uint16_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":699 + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< + * ctypedef npy_uint64 uint64_t + * #ctypedef npy_uint96 uint96_t + */ +typedef npy_uint32 __pyx_t_5numpy_uint32_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":700 + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< + * #ctypedef npy_uint96 uint96_t + * #ctypedef npy_uint128 uint128_t + */ +typedef npy_uint64 __pyx_t_5numpy_uint64_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":704 + * #ctypedef npy_uint128 uint128_t + * + * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< + * ctypedef npy_float64 float64_t + * #ctypedef npy_float80 float80_t + */ +typedef npy_float32 __pyx_t_5numpy_float32_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":705 + * + * ctypedef npy_float32 float32_t + * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< + * #ctypedef npy_float80 float80_t + * #ctypedef npy_float128 float128_t + */ +typedef npy_float64 __pyx_t_5numpy_float64_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":714 + * # The int types are mapped a bit surprising -- + * # numpy.int corresponds to 'l' and numpy.long to 'q' + * ctypedef npy_long int_t # <<<<<<<<<<<<<< + * ctypedef npy_longlong long_t + * ctypedef npy_longlong longlong_t + */ +typedef npy_long __pyx_t_5numpy_int_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":715 + * # numpy.int corresponds to 'l' and numpy.long to 'q' + * ctypedef npy_long int_t + * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< + * ctypedef npy_longlong longlong_t + * + */ +typedef npy_longlong __pyx_t_5numpy_long_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":716 + * ctypedef npy_long int_t + * ctypedef npy_longlong long_t + * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< + * + * ctypedef npy_ulong uint_t + */ +typedef npy_longlong __pyx_t_5numpy_longlong_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":718 + * ctypedef npy_longlong longlong_t + * + * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< + * ctypedef npy_ulonglong ulong_t + * ctypedef npy_ulonglong ulonglong_t + */ +typedef npy_ulong __pyx_t_5numpy_uint_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":719 + * + * ctypedef npy_ulong uint_t + * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< + * ctypedef npy_ulonglong ulonglong_t + * + */ +typedef npy_ulonglong __pyx_t_5numpy_ulong_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":720 + * ctypedef npy_ulong uint_t + * ctypedef npy_ulonglong ulong_t + * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< + * + * ctypedef npy_intp intp_t + */ +typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":722 + * ctypedef npy_ulonglong ulonglong_t + * + * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< + * ctypedef npy_uintp uintp_t + * + */ +typedef npy_intp __pyx_t_5numpy_intp_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":723 + * + * ctypedef npy_intp intp_t + * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< + * + * ctypedef npy_double float_t + */ +typedef npy_uintp __pyx_t_5numpy_uintp_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":725 + * ctypedef npy_uintp uintp_t + * + * ctypedef npy_double float_t # <<<<<<<<<<<<<< + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t + */ +typedef npy_double __pyx_t_5numpy_float_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":726 + * + * ctypedef npy_double float_t + * ctypedef npy_double double_t # <<<<<<<<<<<<<< + * ctypedef npy_longdouble longdouble_t + * + */ +typedef npy_double __pyx_t_5numpy_double_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":727 + * ctypedef npy_double float_t + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< + * + * ctypedef npy_cfloat cfloat_t + */ +typedef npy_longdouble __pyx_t_5numpy_longdouble_t; +/* Declarations.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< float > __pyx_t_float_complex; + #else + typedef float _Complex __pyx_t_float_complex; + #endif +#else + typedef struct { float real, imag; } __pyx_t_float_complex; +#endif +static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); + +/* Declarations.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< double > __pyx_t_double_complex; + #else + typedef double _Complex __pyx_t_double_complex; + #endif +#else + typedef struct { double real, imag; } __pyx_t_double_complex; +#endif +static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); + + +/*--- Type declarations ---*/ + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":729 + * ctypedef npy_longdouble longdouble_t + * + * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< + * ctypedef npy_cdouble cdouble_t + * ctypedef npy_clongdouble clongdouble_t + */ +typedef npy_cfloat __pyx_t_5numpy_cfloat_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":730 + * + * ctypedef npy_cfloat cfloat_t + * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< + * ctypedef npy_clongdouble clongdouble_t + * + */ +typedef npy_cdouble __pyx_t_5numpy_cdouble_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":731 + * ctypedef npy_cfloat cfloat_t + * ctypedef npy_cdouble cdouble_t + * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< + * + * ctypedef npy_cdouble complex_t + */ +typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":733 + * ctypedef npy_clongdouble clongdouble_t + * + * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew1(a): + */ +typedef npy_cdouble __pyx_t_5numpy_complex_t; + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* ArgTypeTest.proto */ +#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ + ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\ + __Pyx__ArgTypeTest(obj, type, name, exact)) +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); + +/* IsLittleEndian.proto */ +static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); + +/* BufferFormatCheck.proto */ +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type); + +/* BufferGetAndValidate.proto */ +#define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)\ + ((obj == Py_None || obj == NULL) ?\ + (__Pyx_ZeroBuffer(buf), 0) :\ + __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)) +static int __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj, + __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); +static void __Pyx_ZeroBuffer(Py_buffer* buf); +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); +static Py_ssize_t __Pyx_minusones[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; +static Py_ssize_t __Pyx_zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* ExtTypeTest.proto */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +/* GetItemInt.proto */ +#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ + __Pyx_GetItemInt_Generic(o, to_py_func(i)))) +#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck); + +/* ObjectGetItem.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); +#else +#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) +#endif + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif +#if CYTHON_FAST_PYCALL + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif // CYTHON_FAST_PYCALL +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectCall2Args.proto */ +static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); + +/* BufferIndexError.proto */ +static void __Pyx_RaiseBufferIndexError(int axis); + +#define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0) +#define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1) +/* BufferFallbackError.proto */ +static void __Pyx_RaiseBufferFallbackError(void); + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* GetTopmostException.proto */ +#if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); +#endif + +/* SaveResetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +#else +#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) +#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) +#endif + +/* PyErrExceptionMatches.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) +static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); +#else +#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) +#endif + +/* GetException.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); +#endif + +/* RaiseException.proto */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto +#define __PYX_HAVE_RT_ImportType_proto +enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 +}; +static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); +#endif + +/* Import.proto */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* BufferStructDeclare.proto */ +typedef struct { + Py_ssize_t shape, strides, suboffsets; +} __Pyx_Buf_DimInfo; +typedef struct { + size_t refcount; + Py_buffer pybuffer; +} __Pyx_Buffer; +typedef struct { + __Pyx_Buffer *rcbuffer; + char *data; + __Pyx_Buf_DimInfo diminfo[8]; +} __Pyx_LocalBuf_ND; + +#if PY_MAJOR_VERSION < 3 + static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); + static void __Pyx_ReleaseBuffer(Py_buffer *view); +#else + #define __Pyx_GetBuffer PyObject_GetBuffer + #define __Pyx_ReleaseBuffer PyBuffer_Release +#endif + + +/* GCCDiagnostics.proto */ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#define __Pyx_HAS_GCC_DIAGNOSTIC +#endif + +/* RealImag.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #define __Pyx_CREAL(z) ((z).real()) + #define __Pyx_CIMAG(z) ((z).imag()) + #else + #define __Pyx_CREAL(z) (__real__(z)) + #define __Pyx_CIMAG(z) (__imag__(z)) + #endif +#else + #define __Pyx_CREAL(z) ((z).real) + #define __Pyx_CIMAG(z) ((z).imag) +#endif +#if defined(__cplusplus) && CYTHON_CCOMPLEX\ + && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) + #define __Pyx_SET_CREAL(z,x) ((z).real(x)) + #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) +#else + #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) + #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) +#endif + +/* Arithmetic.proto */ +#if CYTHON_CCOMPLEX + #define __Pyx_c_eq_float(a, b) ((a)==(b)) + #define __Pyx_c_sum_float(a, b) ((a)+(b)) + #define __Pyx_c_diff_float(a, b) ((a)-(b)) + #define __Pyx_c_prod_float(a, b) ((a)*(b)) + #define __Pyx_c_quot_float(a, b) ((a)/(b)) + #define __Pyx_c_neg_float(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero_float(z) ((z)==(float)0) + #define __Pyx_c_conj_float(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs_float(z) (::std::abs(z)) + #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero_float(z) ((z)==0) + #define __Pyx_c_conj_float(z) (conjf(z)) + #if 1 + #define __Pyx_c_abs_float(z) (cabsf(z)) + #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); + static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); + #if 1 + static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); + #endif +#endif + +/* Arithmetic.proto */ +#if CYTHON_CCOMPLEX + #define __Pyx_c_eq_double(a, b) ((a)==(b)) + #define __Pyx_c_sum_double(a, b) ((a)+(b)) + #define __Pyx_c_diff_double(a, b) ((a)-(b)) + #define __Pyx_c_prod_double(a, b) ((a)*(b)) + #define __Pyx_c_quot_double(a, b) ((a)/(b)) + #define __Pyx_c_neg_double(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero_double(z) ((z)==(double)0) + #define __Pyx_c_conj_double(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs_double(z) (::std::abs(z)) + #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero_double(z) ((z)==0) + #define __Pyx_c_conj_double(z) (conj(z)) + #if 1 + #define __Pyx_c_abs_double(z) (cabs(z)) + #define __Pyx_c_pow_double(a, b) (cpow(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); + static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); + #if 1 + static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); + #endif +#endif + +/* CIntFromPy.proto */ +static CYTHON_INLINE npy_int32 __Pyx_PyInt_As_npy_int32(PyObject *); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + +/* Module declarations from 'cpython.buffer' */ + +/* Module declarations from 'libc.string' */ + +/* Module declarations from 'libc.stdio' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.type' */ +static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; + +/* Module declarations from 'cpython' */ + +/* Module declarations from 'cpython.object' */ + +/* Module declarations from 'cpython.ref' */ + +/* Module declarations from 'cpython.mem' */ + +/* Module declarations from 'numpy' */ + +/* Module declarations from 'numpy' */ +static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; +static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; +static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; +static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; +static PyTypeObject *__pyx_ptype_5numpy_generic = 0; +static PyTypeObject *__pyx_ptype_5numpy_number = 0; +static PyTypeObject *__pyx_ptype_5numpy_integer = 0; +static PyTypeObject *__pyx_ptype_5numpy_signedinteger = 0; +static PyTypeObject *__pyx_ptype_5numpy_unsignedinteger = 0; +static PyTypeObject *__pyx_ptype_5numpy_inexact = 0; +static PyTypeObject *__pyx_ptype_5numpy_floating = 0; +static PyTypeObject *__pyx_ptype_5numpy_complexfloating = 0; +static PyTypeObject *__pyx_ptype_5numpy_flexible = 0; +static PyTypeObject *__pyx_ptype_5numpy_character = 0; +static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; + +/* Module declarations from 'gpu_nms' */ +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t = { "float32_t", NULL, sizeof(__pyx_t_5numpy_float32_t), { 0 }, 0, 'R', 0, 0 }; +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t = { "int32_t", NULL, sizeof(__pyx_t_5numpy_int32_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_int32_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_int32_t), 0 }; +#define __Pyx_MODULE_NAME "gpu_nms" +extern int __pyx_module_is_main_gpu_nms; +int __pyx_module_is_main_gpu_nms = 0; + +/* Implementation of 'gpu_nms' */ +static PyObject *__pyx_builtin_ImportError; +static const char __pyx_k_np[] = "np"; +static const char __pyx_k_dets[] = "dets"; +static const char __pyx_k_keep[] = "keep"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_dtype[] = "dtype"; +static const char __pyx_k_int32[] = "int32"; +static const char __pyx_k_numpy[] = "numpy"; +static const char __pyx_k_order[] = "order"; +static const char __pyx_k_zeros[] = "zeros"; +static const char __pyx_k_astype[] = "astype"; +static const char __pyx_k_import[] = "__import__"; +static const char __pyx_k_scores[] = "scores"; +static const char __pyx_k_thresh[] = "thresh"; +static const char __pyx_k_argsort[] = "argsort"; +static const char __pyx_k_gpu_nms[] = "gpu_nms"; +static const char __pyx_k_num_out[] = "num_out"; +static const char __pyx_k_boxes_dim[] = "boxes_dim"; +static const char __pyx_k_boxes_num[] = "boxes_num"; +static const char __pyx_k_device_id[] = "device_id"; +static const char __pyx_k_ImportError[] = "ImportError"; +static const char __pyx_k_gpu_nms_pyx[] = "gpu_nms.pyx"; +static const char __pyx_k_sorted_dets[] = "sorted_dets"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_numpy_core_multiarray_failed_to[] = "numpy.core.multiarray failed to import"; +static const char __pyx_k_numpy_core_umath_failed_to_impor[] = "numpy.core.umath failed to import"; +static PyObject *__pyx_n_s_ImportError; +static PyObject *__pyx_n_s_argsort; +static PyObject *__pyx_n_s_astype; +static PyObject *__pyx_n_s_boxes_dim; +static PyObject *__pyx_n_s_boxes_num; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_dets; +static PyObject *__pyx_n_s_device_id; +static PyObject *__pyx_n_s_dtype; +static PyObject *__pyx_n_s_gpu_nms; +static PyObject *__pyx_kp_s_gpu_nms_pyx; +static PyObject *__pyx_n_s_import; +static PyObject *__pyx_n_s_int32; +static PyObject *__pyx_n_s_keep; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_np; +static PyObject *__pyx_n_s_num_out; +static PyObject *__pyx_n_s_numpy; +static PyObject *__pyx_kp_s_numpy_core_multiarray_failed_to; +static PyObject *__pyx_kp_s_numpy_core_umath_failed_to_impor; +static PyObject *__pyx_n_s_order; +static PyObject *__pyx_n_s_scores; +static PyObject *__pyx_n_s_sorted_dets; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_n_s_thresh; +static PyObject *__pyx_n_s_zeros; +static PyObject *__pyx_pf_7gpu_nms_gpu_nms(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_dets, PyObject *__pyx_v_thresh, __pyx_t_5numpy_int32_t __pyx_v_device_id); /* proto */ +static PyObject *__pyx_int_4; +static PyObject *__pyx_int_neg_1; +static PyObject *__pyx_slice_; +static PyObject *__pyx_slice__3; +static PyObject *__pyx_tuple__2; +static PyObject *__pyx_tuple__4; +static PyObject *__pyx_tuple__5; +static PyObject *__pyx_tuple__6; +static PyObject *__pyx_codeobj__7; +/* Late includes */ + +/* "gpu_nms.pyx":19 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_7gpu_nms_1gpu_nms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_7gpu_nms_1gpu_nms = {"gpu_nms", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7gpu_nms_1gpu_nms, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_7gpu_nms_1gpu_nms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyArrayObject *__pyx_v_dets = 0; + PyObject *__pyx_v_thresh = 0; + __pyx_t_5numpy_int32_t __pyx_v_device_id; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("gpu_nms (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_dets,&__pyx_n_s_thresh,&__pyx_n_s_device_id,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_dets)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_thresh)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("gpu_nms", 0, 2, 3, 1); __PYX_ERR(0, 19, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (kw_args > 0) { + PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_device_id); + if (value) { values[2] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "gpu_nms") < 0)) __PYX_ERR(0, 19, __pyx_L3_error) + } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + __pyx_v_dets = ((PyArrayObject *)values[0]); + __pyx_v_thresh = ((PyObject*)values[1]); + if (values[2]) { + __pyx_v_device_id = __Pyx_PyInt_As_npy_int32(values[2]); if (unlikely((__pyx_v_device_id == ((npy_int32)-1)) && PyErr_Occurred())) __PYX_ERR(0, 20, __pyx_L3_error) + } else { + __pyx_v_device_id = ((__pyx_t_5numpy_int32_t)0); + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("gpu_nms", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 19, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("gpu_nms.gpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dets), __pyx_ptype_5numpy_ndarray, 1, "dets", 0))) __PYX_ERR(0, 19, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_thresh), (&PyFloat_Type), 1, "thresh", 1))) __PYX_ERR(0, 19, __pyx_L1_error) + __pyx_r = __pyx_pf_7gpu_nms_gpu_nms(__pyx_self, __pyx_v_dets, __pyx_v_thresh, __pyx_v_device_id); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_7gpu_nms_gpu_nms(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_dets, PyObject *__pyx_v_thresh, __pyx_t_5numpy_int32_t __pyx_v_device_id) { + int __pyx_v_boxes_num; + int __pyx_v_boxes_dim; + int __pyx_v_num_out; + PyArrayObject *__pyx_v_keep = 0; + PyArrayObject *__pyx_v_scores = 0; + PyArrayObject *__pyx_v_order = 0; + PyArrayObject *__pyx_v_sorted_dets = 0; + __Pyx_LocalBuf_ND __pyx_pybuffernd_dets; + __Pyx_Buffer __pyx_pybuffer_dets; + __Pyx_LocalBuf_ND __pyx_pybuffernd_keep; + __Pyx_Buffer __pyx_pybuffer_keep; + __Pyx_LocalBuf_ND __pyx_pybuffernd_order; + __Pyx_Buffer __pyx_pybuffer_order; + __Pyx_LocalBuf_ND __pyx_pybuffernd_scores; + __Pyx_Buffer __pyx_pybuffer_scores; + __Pyx_LocalBuf_ND __pyx_pybuffernd_sorted_dets; + __Pyx_Buffer __pyx_pybuffer_sorted_dets; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + PyArrayObject *__pyx_t_7 = NULL; + PyArrayObject *__pyx_t_8 = NULL; + PyArrayObject *__pyx_t_9 = NULL; + Py_ssize_t __pyx_t_10; + int __pyx_t_11; + Py_ssize_t __pyx_t_12; + Py_ssize_t __pyx_t_13; + float __pyx_t_14; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("gpu_nms", 0); + __pyx_pybuffer_keep.pybuffer.buf = NULL; + __pyx_pybuffer_keep.refcount = 0; + __pyx_pybuffernd_keep.data = NULL; + __pyx_pybuffernd_keep.rcbuffer = &__pyx_pybuffer_keep; + __pyx_pybuffer_scores.pybuffer.buf = NULL; + __pyx_pybuffer_scores.refcount = 0; + __pyx_pybuffernd_scores.data = NULL; + __pyx_pybuffernd_scores.rcbuffer = &__pyx_pybuffer_scores; + __pyx_pybuffer_order.pybuffer.buf = NULL; + __pyx_pybuffer_order.refcount = 0; + __pyx_pybuffernd_order.data = NULL; + __pyx_pybuffernd_order.rcbuffer = &__pyx_pybuffer_order; + __pyx_pybuffer_sorted_dets.pybuffer.buf = NULL; + __pyx_pybuffer_sorted_dets.refcount = 0; + __pyx_pybuffernd_sorted_dets.data = NULL; + __pyx_pybuffernd_sorted_dets.rcbuffer = &__pyx_pybuffer_sorted_dets; + __pyx_pybuffer_dets.pybuffer.buf = NULL; + __pyx_pybuffer_dets.refcount = 0; + __pyx_pybuffernd_dets.data = NULL; + __pyx_pybuffernd_dets.rcbuffer = &__pyx_pybuffer_dets; + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dets.rcbuffer->pybuffer, (PyObject*)__pyx_v_dets, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) __PYX_ERR(0, 19, __pyx_L1_error) + } + __pyx_pybuffernd_dets.diminfo[0].strides = __pyx_pybuffernd_dets.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_dets.diminfo[0].shape = __pyx_pybuffernd_dets.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_dets.diminfo[1].strides = __pyx_pybuffernd_dets.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_dets.diminfo[1].shape = __pyx_pybuffernd_dets.rcbuffer->pybuffer.shape[1]; + + /* "gpu_nms.pyx":21 + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] # <<<<<<<<<<<<<< + * cdef int boxes_dim = dets.shape[1] + * cdef int num_out + */ + __pyx_v_boxes_num = (__pyx_v_dets->dimensions[0]); + + /* "gpu_nms.pyx":22 + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + * cdef int boxes_dim = dets.shape[1] # <<<<<<<<<<<<<< + * cdef int num_out + * cdef np.ndarray[np.int32_t, ndim=1] \ + */ + __pyx_v_boxes_dim = (__pyx_v_dets->dimensions[1]); + + /* "gpu_nms.pyx":25 + * cdef int num_out + * cdef np.ndarray[np.int32_t, ndim=1] \ + * keep = np.zeros(boxes_num, dtype=np.int32) # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] \ + * scores = dets[:, 4] + */ + __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_boxes_num); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_int32); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_5) < 0) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 25, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 25, __pyx_L1_error) + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_keep.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_keep = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_keep.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 24, __pyx_L1_error) + } else {__pyx_pybuffernd_keep.diminfo[0].strides = __pyx_pybuffernd_keep.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_keep.diminfo[0].shape = __pyx_pybuffernd_keep.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_6 = 0; + __pyx_v_keep = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + /* "gpu_nms.pyx":27 + * keep = np.zeros(boxes_num, dtype=np.int32) + * cdef np.ndarray[np.float32_t, ndim=1] \ + * scores = dets[:, 4] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.int32_t, ndim=1] \ + * order = scores.argsort()[::-1].astype(np.int32) + */ + __pyx_t_5 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_tuple__2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 27, __pyx_L1_error) + __pyx_t_7 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_scores.rcbuffer->pybuffer, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_scores = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_scores.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 26, __pyx_L1_error) + } else {__pyx_pybuffernd_scores.diminfo[0].strides = __pyx_pybuffernd_scores.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_scores.diminfo[0].shape = __pyx_pybuffernd_scores.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_7 = 0; + __pyx_v_scores = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + /* "gpu_nms.pyx":29 + * scores = dets[:, 4] + * cdef np.ndarray[np.int32_t, ndim=1] \ + * order = scores.argsort()[::-1].astype(np.int32) # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_scores), __pyx_n_s_argsort); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_slice__3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_astype); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_int32); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + __pyx_t_5 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 29, __pyx_L1_error) + __pyx_t_8 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_order.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_order = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_order.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 28, __pyx_L1_error) + } else {__pyx_pybuffernd_order.diminfo[0].strides = __pyx_pybuffernd_order.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_order.diminfo[0].shape = __pyx_pybuffernd_order.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_8 = 0; + __pyx_v_order = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + /* "gpu_nms.pyx":31 + * order = scores.argsort()[::-1].astype(np.int32) + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] # <<<<<<<<<<<<<< + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + * keep = keep[:num_out] + */ + __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 31, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_INCREF(((PyObject *)__pyx_v_order)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_order)); + PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_order)); + __Pyx_INCREF(__pyx_slice_); + __Pyx_GIVEREF(__pyx_slice_); + PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_slice_); + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 31, __pyx_L1_error) + __pyx_t_9 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_sorted_dets = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 30, __pyx_L1_error) + } else {__pyx_pybuffernd_sorted_dets.diminfo[0].strides = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_sorted_dets.diminfo[0].shape = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_sorted_dets.diminfo[1].strides = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_sorted_dets.diminfo[1].shape = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.shape[1]; + } + } + __pyx_t_9 = 0; + __pyx_v_sorted_dets = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "gpu_nms.pyx":32 + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) # <<<<<<<<<<<<<< + * keep = keep[:num_out] + * return list(order[keep]) + */ + __pyx_t_10 = 0; + __pyx_t_11 = -1; + if (__pyx_t_10 < 0) { + __pyx_t_10 += __pyx_pybuffernd_keep.diminfo[0].shape; + if (unlikely(__pyx_t_10 < 0)) __pyx_t_11 = 0; + } else if (unlikely(__pyx_t_10 >= __pyx_pybuffernd_keep.diminfo[0].shape)) __pyx_t_11 = 0; + if (unlikely(__pyx_t_11 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_11); + __PYX_ERR(0, 32, __pyx_L1_error) + } + __pyx_t_12 = 0; + __pyx_t_13 = 0; + __pyx_t_11 = -1; + if (__pyx_t_12 < 0) { + __pyx_t_12 += __pyx_pybuffernd_sorted_dets.diminfo[0].shape; + if (unlikely(__pyx_t_12 < 0)) __pyx_t_11 = 0; + } else if (unlikely(__pyx_t_12 >= __pyx_pybuffernd_sorted_dets.diminfo[0].shape)) __pyx_t_11 = 0; + if (__pyx_t_13 < 0) { + __pyx_t_13 += __pyx_pybuffernd_sorted_dets.diminfo[1].shape; + if (unlikely(__pyx_t_13 < 0)) __pyx_t_11 = 1; + } else if (unlikely(__pyx_t_13 >= __pyx_pybuffernd_sorted_dets.diminfo[1].shape)) __pyx_t_11 = 1; + if (unlikely(__pyx_t_11 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_11); + __PYX_ERR(0, 32, __pyx_L1_error) + } + __pyx_t_14 = __pyx_PyFloat_AsFloat(__pyx_v_thresh); if (unlikely((__pyx_t_14 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 32, __pyx_L1_error) + _nms((&(*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int32_t *, __pyx_pybuffernd_keep.rcbuffer->pybuffer.buf, __pyx_t_10, __pyx_pybuffernd_keep.diminfo[0].strides))), (&__pyx_v_num_out), (&(*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_sorted_dets.diminfo[0].strides, __pyx_t_13, __pyx_pybuffernd_sorted_dets.diminfo[1].strides))), __pyx_v_boxes_num, __pyx_v_boxes_dim, __pyx_t_14, __pyx_v_device_id); + + /* "gpu_nms.pyx":33 + * sorted_dets = dets[order, :] + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + * keep = keep[:num_out] # <<<<<<<<<<<<<< + * return list(order[keep]) + */ + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_num_out); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 33, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PySlice_New(Py_None, __pyx_t_1, Py_None); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 33, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_keep), __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 33, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 33, __pyx_L1_error) + __pyx_t_6 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_keep.rcbuffer->pybuffer); + __pyx_t_11 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_keep.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack); + if (unlikely(__pyx_t_11 < 0)) { + PyErr_Fetch(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_keep.rcbuffer->pybuffer, (PyObject*)__pyx_v_keep, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_15); Py_XDECREF(__pyx_t_16); Py_XDECREF(__pyx_t_17); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + __pyx_t_15 = __pyx_t_16 = __pyx_t_17 = 0; + } + __pyx_pybuffernd_keep.diminfo[0].strides = __pyx_pybuffernd_keep.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_keep.diminfo[0].shape = __pyx_pybuffernd_keep.rcbuffer->pybuffer.shape[0]; + if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 33, __pyx_L1_error) + } + __pyx_t_6 = 0; + __Pyx_DECREF_SET(__pyx_v_keep, ((PyArrayObject *)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "gpu_nms.pyx":34 + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + * keep = keep[:num_out] + * return list(order[keep]) # <<<<<<<<<<<<<< + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_order), ((PyObject *)__pyx_v_keep)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 34, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = PySequence_List(__pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 34, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_5; + __pyx_t_5 = 0; + goto __pyx_L0; + + /* "gpu_nms.pyx":19 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dets.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_keep.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_order.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_scores.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("gpu_nms.gpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dets.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_keep.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_order.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_scores.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer); + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_keep); + __Pyx_XDECREF((PyObject *)__pyx_v_scores); + __Pyx_XDECREF((PyObject *)__pyx_v_order); + __Pyx_XDECREF((PyObject *)__pyx_v_sorted_dets); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":735 + * ctypedef npy_cdouble complex_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":736 + * + * cdef inline object PyArray_MultiIterNew1(a): + * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew2(a, b): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 736, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":735 + * ctypedef npy_cdouble complex_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":738 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":739 + * + * cdef inline object PyArray_MultiIterNew2(a, b): + * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 739, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":738 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":741 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":742 + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): + * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 742, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":741 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":744 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":745 + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): + * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 745, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":744 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":747 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":748 + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 748, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":747 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":750 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":751 + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< + * return d.subarray.shape + * else: + */ + __pyx_t_1 = (PyDataType_HASSUBARRAY(__pyx_v_d) != 0); + if (__pyx_t_1) { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":752 + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape # <<<<<<<<<<<<<< + * else: + * return () + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape)); + __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":751 + * + * cdef inline tuple PyDataType_SHAPE(dtype d): + * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< + * return d.subarray.shape + * else: + */ + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":754 + * return d.subarray.shape + * else: + * return () # <<<<<<<<<<<<<< + * + * + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_empty_tuple); + __pyx_r = __pyx_empty_tuple; + goto __pyx_L0; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":750 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< + * if PyDataType_HASSUBARRAY(d): + * return d.subarray.shape + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":929 + * int _import_umath() except -1 + * + * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) + */ + +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("set_array_base", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":930 + * + * cdef inline void set_array_base(ndarray arr, object base): + * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< + * PyArray_SetBaseObject(arr, base) + * + */ + Py_INCREF(__pyx_v_base); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":931 + * cdef inline void set_array_base(ndarray arr, object base): + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< + * + * cdef inline object get_array_base(ndarray arr): + */ + (void)(PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base)); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":929 + * int _import_umath() except -1 + * + * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< + * Py_INCREF(base) # important to do this before stealing the reference below! + * PyArray_SetBaseObject(arr, base) + */ + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":933 + * PyArray_SetBaseObject(arr, base) + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * base = PyArray_BASE(arr) + * if base is NULL: + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { + PyObject *__pyx_v_base; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + __Pyx_RefNannySetupContext("get_array_base", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":934 + * + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< + * if base is NULL: + * return None + */ + __pyx_v_base = PyArray_BASE(__pyx_v_arr); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":935 + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) + * if base is NULL: # <<<<<<<<<<<<<< + * return None + * return base + */ + __pyx_t_1 = ((__pyx_v_base == NULL) != 0); + if (__pyx_t_1) { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":936 + * base = PyArray_BASE(arr) + * if base is NULL: + * return None # <<<<<<<<<<<<<< + * return base + * + */ + __Pyx_XDECREF(__pyx_r); + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":935 + * cdef inline object get_array_base(ndarray arr): + * base = PyArray_BASE(arr) + * if base is NULL: # <<<<<<<<<<<<<< + * return None + * return base + */ + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":937 + * if base is NULL: + * return None + * return base # <<<<<<<<<<<<<< + * + * # Versions of the import_* functions which are more suitable for + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_base)); + __pyx_r = ((PyObject *)__pyx_v_base); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":933 + * PyArray_SetBaseObject(arr, base) + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * base = PyArray_BASE(arr) + * if base is NULL: + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":941 + * # Versions of the import_* functions which are more suitable for + * # Cython code. + * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< + * try: + * __pyx_import_array() + */ + +static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_array", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":942 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":943 + * cdef inline int import_array() except -1: + * try: + * __pyx_import_array() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy.core.multiarray failed to import") + */ + __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 943, __pyx_L3_error) + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":942 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":944 + * try: + * __pyx_import_array() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy.core.multiarray failed to import") + * + */ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 944, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":945 + * __pyx_import_array() + * except Exception: + * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_umath() except -1: + */ + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 945, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(1, 945, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":942 + * # Cython code. + * cdef inline int import_array() except -1: + * try: # <<<<<<<<<<<<<< + * __pyx_import_array() + * except Exception: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":941 + * # Versions of the import_* functions which are more suitable for + * # Cython code. + * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< + * try: + * __pyx_import_array() + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":947 + * raise ImportError("numpy.core.multiarray failed to import") + * + * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + +static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_umath", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":948 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":949 + * cdef inline int import_umath() except -1: + * try: + * _import_umath() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy.core.umath failed to import") + */ + __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 949, __pyx_L3_error) + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":948 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":950 + * try: + * _import_umath() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy.core.umath failed to import") + * + */ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 950, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":951 + * _import_umath() + * except Exception: + * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_ufunc() except -1: + */ + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 951, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(1, 951, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":948 + * + * cdef inline int import_umath() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":947 + * raise ImportError("numpy.core.multiarray failed to import") + * + * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":953 + * raise ImportError("numpy.core.umath failed to import") + * + * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + +static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { + int __pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("import_ufunc", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":954 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + { + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); + __Pyx_XGOTREF(__pyx_t_1); + __Pyx_XGOTREF(__pyx_t_2); + __Pyx_XGOTREF(__pyx_t_3); + /*try:*/ { + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":955 + * cdef inline int import_ufunc() except -1: + * try: + * _import_umath() # <<<<<<<<<<<<<< + * except Exception: + * raise ImportError("numpy.core.umath failed to import") + */ + __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 955, __pyx_L3_error) + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":954 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + } + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + goto __pyx_L8_try_end; + __pyx_L3_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":956 + * try: + * _import_umath() + * except Exception: # <<<<<<<<<<<<<< + * raise ImportError("numpy.core.umath failed to import") + * + */ + __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); + if (__pyx_t_4) { + __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); + if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 956, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GOTREF(__pyx_t_6); + __Pyx_GOTREF(__pyx_t_7); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":957 + * _import_umath() + * except Exception: + * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< + * + * cdef extern from *: + */ + __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 957, __pyx_L5_except_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_Raise(__pyx_t_8, 0, 0, 0); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __PYX_ERR(1, 957, __pyx_L5_except_error) + } + goto __pyx_L5_except_error; + __pyx_L5_except_error:; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":954 + * + * cdef inline int import_ufunc() except -1: + * try: # <<<<<<<<<<<<<< + * _import_umath() + * except Exception: + */ + __Pyx_XGIVEREF(__pyx_t_1); + __Pyx_XGIVEREF(__pyx_t_2); + __Pyx_XGIVEREF(__pyx_t_3); + __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); + goto __pyx_L1_error; + __pyx_L8_try_end:; + } + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":953 + * raise ImportError("numpy.core.umath failed to import") + * + * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< + * try: + * _import_umath() + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":967 + * + * + * cdef inline bint is_timedelta64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.timedelta64)` + */ + +static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_obj) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("is_timedelta64_object", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":979 + * bool + * """ + * return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type) # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyTimedeltaArrType_Type)); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":967 + * + * + * cdef inline bint is_timedelta64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.timedelta64)` + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":982 + * + * + * cdef inline bint is_datetime64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.datetime64)` + */ + +static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_obj) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("is_datetime64_object", 0); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":994 + * bool + * """ + * return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type) # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyDatetimeArrType_Type)); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":982 + * + * + * cdef inline bint is_datetime64_object(object obj): # <<<<<<<<<<<<<< + * """ + * Cython equivalent of `isinstance(obj, np.datetime64)` + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":997 + * + * + * cdef inline npy_datetime get_datetime64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy datetime64 object + */ + +static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject *__pyx_v_obj) { + npy_datetime __pyx_r; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1004 + * also needed. That can be found using `get_datetime64_unit`. + * """ + * return (obj).obval # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = ((PyDatetimeScalarObject *)__pyx_v_obj)->obval; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":997 + * + * + * cdef inline npy_datetime get_datetime64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy datetime64 object + */ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1007 + * + * + * cdef inline npy_timedelta get_timedelta64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy timedelta64 object + */ + +static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject *__pyx_v_obj) { + npy_timedelta __pyx_r; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1011 + * returns the int64 value underlying scalar numpy timedelta64 object + * """ + * return (obj).obval # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = ((PyTimedeltaScalarObject *)__pyx_v_obj)->obval; + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1007 + * + * + * cdef inline npy_timedelta get_timedelta64_value(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the int64 value underlying scalar numpy timedelta64 object + */ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +/* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1014 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. + */ + +static CYTHON_INLINE NPY_DATETIMEUNIT __pyx_f_5numpy_get_datetime64_unit(PyObject *__pyx_v_obj) { + NPY_DATETIMEUNIT __pyx_r; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1018 + * returns the unit part of the dtype for a numpy datetime64 object. + * """ + * return (obj).obmeta.base # <<<<<<<<<<<<<< + */ + __pyx_r = ((NPY_DATETIMEUNIT)((PyDatetimeScalarObject *)__pyx_v_obj)->obmeta.base); + goto __pyx_L0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1014 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. + */ + + /* function exit code */ + __pyx_L0:; + return __pyx_r; +} + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_gpu_nms(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_gpu_nms}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "gpu_nms", + 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, + {&__pyx_n_s_argsort, __pyx_k_argsort, sizeof(__pyx_k_argsort), 0, 0, 1, 1}, + {&__pyx_n_s_astype, __pyx_k_astype, sizeof(__pyx_k_astype), 0, 0, 1, 1}, + {&__pyx_n_s_boxes_dim, __pyx_k_boxes_dim, sizeof(__pyx_k_boxes_dim), 0, 0, 1, 1}, + {&__pyx_n_s_boxes_num, __pyx_k_boxes_num, sizeof(__pyx_k_boxes_num), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_dets, __pyx_k_dets, sizeof(__pyx_k_dets), 0, 0, 1, 1}, + {&__pyx_n_s_device_id, __pyx_k_device_id, sizeof(__pyx_k_device_id), 0, 0, 1, 1}, + {&__pyx_n_s_dtype, __pyx_k_dtype, sizeof(__pyx_k_dtype), 0, 0, 1, 1}, + {&__pyx_n_s_gpu_nms, __pyx_k_gpu_nms, sizeof(__pyx_k_gpu_nms), 0, 0, 1, 1}, + {&__pyx_kp_s_gpu_nms_pyx, __pyx_k_gpu_nms_pyx, sizeof(__pyx_k_gpu_nms_pyx), 0, 0, 1, 0}, + {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, + {&__pyx_n_s_int32, __pyx_k_int32, sizeof(__pyx_k_int32), 0, 0, 1, 1}, + {&__pyx_n_s_keep, __pyx_k_keep, sizeof(__pyx_k_keep), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, + {&__pyx_n_s_num_out, __pyx_k_num_out, sizeof(__pyx_k_num_out), 0, 0, 1, 1}, + {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, + {&__pyx_kp_s_numpy_core_multiarray_failed_to, __pyx_k_numpy_core_multiarray_failed_to, sizeof(__pyx_k_numpy_core_multiarray_failed_to), 0, 0, 1, 0}, + {&__pyx_kp_s_numpy_core_umath_failed_to_impor, __pyx_k_numpy_core_umath_failed_to_impor, sizeof(__pyx_k_numpy_core_umath_failed_to_impor), 0, 0, 1, 0}, + {&__pyx_n_s_order, __pyx_k_order, sizeof(__pyx_k_order), 0, 0, 1, 1}, + {&__pyx_n_s_scores, __pyx_k_scores, sizeof(__pyx_k_scores), 0, 0, 1, 1}, + {&__pyx_n_s_sorted_dets, __pyx_k_sorted_dets, sizeof(__pyx_k_sorted_dets), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_thresh, __pyx_k_thresh, sizeof(__pyx_k_thresh), 0, 0, 1, 1}, + {&__pyx_n_s_zeros, __pyx_k_zeros, sizeof(__pyx_k_zeros), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(1, 945, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "gpu_nms.pyx":27 + * keep = np.zeros(boxes_num, dtype=np.int32) + * cdef np.ndarray[np.float32_t, ndim=1] \ + * scores = dets[:, 4] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.int32_t, ndim=1] \ + * order = scores.argsort()[::-1].astype(np.int32) + */ + __pyx_slice_ = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice_)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice_); + __Pyx_GIVEREF(__pyx_slice_); + __pyx_tuple__2 = PyTuple_Pack(2, __pyx_slice_, __pyx_int_4); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 27, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__2); + __Pyx_GIVEREF(__pyx_tuple__2); + + /* "gpu_nms.pyx":29 + * scores = dets[:, 4] + * cdef np.ndarray[np.int32_t, ndim=1] \ + * order = scores.argsort()[::-1].astype(np.int32) # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] + */ + __pyx_slice__3 = PySlice_New(Py_None, Py_None, __pyx_int_neg_1); if (unlikely(!__pyx_slice__3)) __PYX_ERR(0, 29, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__3); + __Pyx_GIVEREF(__pyx_slice__3); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":945 + * __pyx_import_array() + * except Exception: + * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_umath() except -1: + */ + __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_s_numpy_core_multiarray_failed_to); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 945, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__4); + __Pyx_GIVEREF(__pyx_tuple__4); + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":951 + * _import_umath() + * except Exception: + * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< + * + * cdef inline int import_ufunc() except -1: + */ + __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_s_numpy_core_umath_failed_to_impor); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 951, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__5); + __Pyx_GIVEREF(__pyx_tuple__5); + + /* "gpu_nms.pyx":19 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + __pyx_tuple__6 = PyTuple_Pack(10, __pyx_n_s_dets, __pyx_n_s_thresh, __pyx_n_s_device_id, __pyx_n_s_boxes_num, __pyx_n_s_boxes_dim, __pyx_n_s_num_out, __pyx_n_s_keep, __pyx_n_s_scores, __pyx_n_s_order, __pyx_n_s_sorted_dets); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 19, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__6); + __Pyx_GIVEREF(__pyx_tuple__6); + __pyx_codeobj__7 = (PyObject*)__Pyx_PyCode_New(3, 0, 10, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__6, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_gpu_nms_pyx, __pyx_n_s_gpu_nms, 19, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__7)) __PYX_ERR(0, 19, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_4 = PyInt_FromLong(4); if (unlikely(!__pyx_int_4)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 200, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_5numpy_dtype = __Pyx_ImportType(__pyx_t_1, "numpy", "dtype", sizeof(PyArray_Descr), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 200, __pyx_L1_error) + __pyx_ptype_5numpy_flatiter = __Pyx_ImportType(__pyx_t_1, "numpy", "flatiter", sizeof(PyArrayIterObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 223, __pyx_L1_error) + __pyx_ptype_5numpy_broadcast = __Pyx_ImportType(__pyx_t_1, "numpy", "broadcast", sizeof(PyArrayMultiIterObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 227, __pyx_L1_error) + __pyx_ptype_5numpy_ndarray = __Pyx_ImportType(__pyx_t_1, "numpy", "ndarray", sizeof(PyArrayObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 239, __pyx_L1_error) + __pyx_ptype_5numpy_generic = __Pyx_ImportType(__pyx_t_1, "numpy", "generic", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_generic) __PYX_ERR(1, 771, __pyx_L1_error) + __pyx_ptype_5numpy_number = __Pyx_ImportType(__pyx_t_1, "numpy", "number", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_number) __PYX_ERR(1, 773, __pyx_L1_error) + __pyx_ptype_5numpy_integer = __Pyx_ImportType(__pyx_t_1, "numpy", "integer", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_integer) __PYX_ERR(1, 775, __pyx_L1_error) + __pyx_ptype_5numpy_signedinteger = __Pyx_ImportType(__pyx_t_1, "numpy", "signedinteger", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_signedinteger) __PYX_ERR(1, 777, __pyx_L1_error) + __pyx_ptype_5numpy_unsignedinteger = __Pyx_ImportType(__pyx_t_1, "numpy", "unsignedinteger", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_unsignedinteger) __PYX_ERR(1, 779, __pyx_L1_error) + __pyx_ptype_5numpy_inexact = __Pyx_ImportType(__pyx_t_1, "numpy", "inexact", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_inexact) __PYX_ERR(1, 781, __pyx_L1_error) + __pyx_ptype_5numpy_floating = __Pyx_ImportType(__pyx_t_1, "numpy", "floating", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_floating) __PYX_ERR(1, 783, __pyx_L1_error) + __pyx_ptype_5numpy_complexfloating = __Pyx_ImportType(__pyx_t_1, "numpy", "complexfloating", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_complexfloating) __PYX_ERR(1, 785, __pyx_L1_error) + __pyx_ptype_5numpy_flexible = __Pyx_ImportType(__pyx_t_1, "numpy", "flexible", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_flexible) __PYX_ERR(1, 787, __pyx_L1_error) + __pyx_ptype_5numpy_character = __Pyx_ImportType(__pyx_t_1, "numpy", "character", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_5numpy_character) __PYX_ERR(1, 789, __pyx_L1_error) + __pyx_ptype_5numpy_ufunc = __Pyx_ImportType(__pyx_t_1, "numpy", "ufunc", sizeof(PyUFuncObject), __Pyx_ImportType_CheckSize_Ignore); + if (!__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 827, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#ifndef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#elif PY_MAJOR_VERSION < 3 +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" void +#else +#define __Pyx_PyMODINIT_FUNC void +#endif +#else +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyObject * +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initgpu_nms(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initgpu_nms(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_gpu_nms(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_gpu_nms(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_gpu_nms(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'gpu_nms' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_gpu_nms(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + PyEval_InitThreads(); + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("gpu_nms", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main_gpu_nms) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "gpu_nms")) { + if (unlikely(PyDict_SetItemString(modules, "gpu_nms", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + (void)__Pyx_modinit_type_init_code(); + if (unlikely(__Pyx_modinit_type_import_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "gpu_nms.pyx":11 + * from __future__ import print_function + * + * import numpy as np # <<<<<<<<<<<<<< + * cimport numpy as np + * + */ + __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "gpu_nms.pyx":14 + * cimport numpy as np + * + * assert sizeof(int) == sizeof(np.int32_t) # <<<<<<<<<<<<<< + * + * cdef extern from "gpu_nms.hpp": + */ + #ifndef CYTHON_WITHOUT_ASSERTIONS + if (unlikely(!Py_OptimizeFlag)) { + if (unlikely(!(((sizeof(int)) == (sizeof(__pyx_t_5numpy_int32_t))) != 0))) { + PyErr_SetNone(PyExc_AssertionError); + __PYX_ERR(0, 14, __pyx_L1_error) + } + } + #endif + + /* "gpu_nms.pyx":19 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7gpu_nms_1gpu_nms, NULL, __pyx_n_s_gpu_nms); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 19, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_gpu_nms, __pyx_t_1) < 0) __PYX_ERR(0, 19, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "gpu_nms.pyx":1 + * # ------------------------------------------------------------------------------ # <<<<<<<<<<<<<< + * # Copyright (c) Microsoft + * # Licensed under the MIT License. + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "../../../anaconda3/envs/HRNet/lib/python3.7/site-packages/numpy/__init__.pxd":1014 + * + * + * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< + * """ + * returns the unit part of the dtype for a numpy datetime64 object. + */ + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init gpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init gpu_nms"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* ArgTypeTest */ +static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) +{ + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + else if (exact) { + #if PY_MAJOR_VERSION == 2 + if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; + #endif + } + else { + if (likely(__Pyx_TypeCheck(obj, type))) return 1; + } + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); + return 0; +} + +/* IsLittleEndian */ +static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) +{ + union { + uint32_t u32; + uint8_t u8[4]; + } S; + S.u32 = 0x01020304; + return S.u8[0] == 4; +} + +/* BufferFormatCheck */ +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type) { + stack[0].field = &ctx->root; + stack[0].parent_offset = 0; + ctx->root.type = type; + ctx->root.name = "buffer dtype"; + ctx->root.offset = 0; + ctx->head = stack; + ctx->head->field = &ctx->root; + ctx->fmt_offset = 0; + ctx->head->parent_offset = 0; + ctx->new_packmode = '@'; + ctx->enc_packmode = '@'; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->is_complex = 0; + ctx->is_valid_array = 0; + ctx->struct_alignment = 0; + while (type->typegroup == 'S') { + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = 0; + type = type->fields->type; + } +} +static int __Pyx_BufFmt_ParseNumber(const char** ts) { + int count; + const char* t = *ts; + if (*t < '0' || *t > '9') { + return -1; + } else { + count = *t++ - '0'; + while (*t >= '0' && *t <= '9') { + count *= 10; + count += *t++ - '0'; + } + } + *ts = t; + return count; +} +static int __Pyx_BufFmt_ExpectNumber(const char **ts) { + int number = __Pyx_BufFmt_ParseNumber(ts); + if (number == -1) + PyErr_Format(PyExc_ValueError,\ + "Does not understand character buffer dtype format string ('%c')", **ts); + return number; +} +static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { + PyErr_Format(PyExc_ValueError, + "Unexpected format string character: '%c'", ch); +} +static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { + switch (ch) { + case '?': return "'bool'"; + case 'c': return "'char'"; + case 'b': return "'signed char'"; + case 'B': return "'unsigned char'"; + case 'h': return "'short'"; + case 'H': return "'unsigned short'"; + case 'i': return "'int'"; + case 'I': return "'unsigned int'"; + case 'l': return "'long'"; + case 'L': return "'unsigned long'"; + case 'q': return "'long long'"; + case 'Q': return "'unsigned long long'"; + case 'f': return (is_complex ? "'complex float'" : "'float'"); + case 'd': return (is_complex ? "'complex double'" : "'double'"); + case 'g': return (is_complex ? "'complex long double'" : "'long double'"); + case 'T': return "a struct"; + case 'O': return "Python object"; + case 'P': return "a pointer"; + case 's': case 'p': return "a string"; + case 0: return "end"; + default: return "unparseable format string"; + } +} +static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return 2; + case 'i': case 'I': case 'l': case 'L': return 4; + case 'q': case 'Q': return 8; + case 'f': return (is_complex ? 8 : 4); + case 'd': return (is_complex ? 16 : 8); + case 'g': { + PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); + return 0; + } + case 'O': case 'P': return sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(short); + case 'i': case 'I': return sizeof(int); + case 'l': case 'L': return sizeof(long); + #ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(PY_LONG_LONG); + #endif + case 'f': return sizeof(float) * (is_complex ? 2 : 1); + case 'd': return sizeof(double) * (is_complex ? 2 : 1); + case 'g': return sizeof(long double) * (is_complex ? 2 : 1); + case 'O': case 'P': return sizeof(void*); + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +typedef struct { char c; short x; } __Pyx_st_short; +typedef struct { char c; int x; } __Pyx_st_int; +typedef struct { char c; long x; } __Pyx_st_long; +typedef struct { char c; float x; } __Pyx_st_float; +typedef struct { char c; double x; } __Pyx_st_double; +typedef struct { char c; long double x; } __Pyx_st_longdouble; +typedef struct { char c; void *x; } __Pyx_st_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; +#endif +static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_st_float) - sizeof(float); + case 'd': return sizeof(__Pyx_st_double) - sizeof(double); + case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +/* These are for computing the padding at the end of the struct to align + on the first member of the struct. This will probably the same as above, + but we don't have any guarantees. + */ +typedef struct { short x; char c; } __Pyx_pad_short; +typedef struct { int x; char c; } __Pyx_pad_int; +typedef struct { long x; char c; } __Pyx_pad_long; +typedef struct { float x; char c; } __Pyx_pad_float; +typedef struct { double x; char c; } __Pyx_pad_double; +typedef struct { long double x; char c; } __Pyx_pad_longdouble; +typedef struct { void *x; char c; } __Pyx_pad_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; +#endif +static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); + case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); + case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { + switch (ch) { + case 'c': + return 'H'; + case 'b': case 'h': case 'i': + case 'l': case 'q': case 's': case 'p': + return 'I'; + case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': + return 'U'; + case 'f': case 'd': case 'g': + return (is_complex ? 'C' : 'R'); + case 'O': + return 'O'; + case 'P': + return 'P'; + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { + if (ctx->head == NULL || ctx->head->field == &ctx->root) { + const char* expected; + const char* quote; + if (ctx->head == NULL) { + expected = "end"; + quote = ""; + } else { + expected = ctx->head->field->type->name; + quote = "'"; + } + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected %s%s%s but got %s", + quote, expected, quote, + __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); + } else { + __Pyx_StructField* field = ctx->head->field; + __Pyx_StructField* parent = (ctx->head - 1)->field; + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", + field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), + parent->type->name, field->name); + } +} +static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { + char group; + size_t size, offset, arraysize = 1; + if (ctx->enc_type == 0) return 0; + if (ctx->head->field->type->arraysize[0]) { + int i, ndim = 0; + if (ctx->enc_type == 's' || ctx->enc_type == 'p') { + ctx->is_valid_array = ctx->head->field->type->ndim == 1; + ndim = 1; + if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { + PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %zu", + ctx->head->field->type->arraysize[0], ctx->enc_count); + return -1; + } + } + if (!ctx->is_valid_array) { + PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", + ctx->head->field->type->ndim, ndim); + return -1; + } + for (i = 0; i < ctx->head->field->type->ndim; i++) { + arraysize *= ctx->head->field->type->arraysize[i]; + } + ctx->is_valid_array = 0; + ctx->enc_count = 1; + } + group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); + do { + __Pyx_StructField* field = ctx->head->field; + __Pyx_TypeInfo* type = field->type; + if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { + size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); + } else { + size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); + } + if (ctx->enc_packmode == '@') { + size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); + size_t align_mod_offset; + if (align_at == 0) return -1; + align_mod_offset = ctx->fmt_offset % align_at; + if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; + if (ctx->struct_alignment == 0) + ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, + ctx->is_complex); + } + if (type->size != size || type->typegroup != group) { + if (type->typegroup == 'C' && type->fields != NULL) { + size_t parent_offset = ctx->head->parent_offset + field->offset; + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = parent_offset; + continue; + } + if ((type->typegroup == 'H' || group == 'H') && type->size == size) { + } else { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + } + offset = ctx->head->parent_offset + field->offset; + if (ctx->fmt_offset != offset) { + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", + (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); + return -1; + } + ctx->fmt_offset += size; + if (arraysize) + ctx->fmt_offset += (arraysize - 1) * size; + --ctx->enc_count; + while (1) { + if (field == &ctx->root) { + ctx->head = NULL; + if (ctx->enc_count != 0) { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + break; + } + ctx->head->field = ++field; + if (field->type == NULL) { + --ctx->head; + field = ctx->head->field; + continue; + } else if (field->type->typegroup == 'S') { + size_t parent_offset = ctx->head->parent_offset + field->offset; + if (field->type->fields->type == NULL) continue; + field = field->type->fields; + ++ctx->head; + ctx->head->field = field; + ctx->head->parent_offset = parent_offset; + break; + } else { + break; + } + } + } while (ctx->enc_count); + ctx->enc_type = 0; + ctx->is_complex = 0; + return 0; +} +static PyObject * +__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) +{ + const char *ts = *tsp; + int i = 0, number, ndim; + ++ts; + if (ctx->new_count != 1) { + PyErr_SetString(PyExc_ValueError, + "Cannot handle repeated arrays in format string"); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ndim = ctx->head->field->type->ndim; + while (*ts && *ts != ')') { + switch (*ts) { + case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; + default: break; + } + number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return NULL; + if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) + return PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %d", + ctx->head->field->type->arraysize[i], number); + if (*ts != ',' && *ts != ')') + return PyErr_Format(PyExc_ValueError, + "Expected a comma in format string, got '%c'", *ts); + if (*ts == ',') ts++; + i++; + } + if (i != ndim) + return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", + ctx->head->field->type->ndim, i); + if (!*ts) { + PyErr_SetString(PyExc_ValueError, + "Unexpected end of format string, expected ')'"); + return NULL; + } + ctx->is_valid_array = 1; + ctx->new_count = 1; + *tsp = ++ts; + return Py_None; +} +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { + int got_Z = 0; + while (1) { + switch(*ts) { + case 0: + if (ctx->enc_type != 0 && ctx->head == NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + if (ctx->head != NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + return ts; + case ' ': + case '\r': + case '\n': + ++ts; + break; + case '<': + if (!__Pyx_Is_Little_Endian()) { + PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '>': + case '!': + if (__Pyx_Is_Little_Endian()) { + PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '=': + case '@': + case '^': + ctx->new_packmode = *ts++; + break; + case 'T': + { + const char* ts_after_sub; + size_t i, struct_count = ctx->new_count; + size_t struct_alignment = ctx->struct_alignment; + ctx->new_count = 1; + ++ts; + if (*ts != '{') { + PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + ctx->enc_count = 0; + ctx->struct_alignment = 0; + ++ts; + ts_after_sub = ts; + for (i = 0; i != struct_count; ++i) { + ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); + if (!ts_after_sub) return NULL; + } + ts = ts_after_sub; + if (struct_alignment) ctx->struct_alignment = struct_alignment; + } + break; + case '}': + { + size_t alignment = ctx->struct_alignment; + ++ts; + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + if (alignment && ctx->fmt_offset % alignment) { + ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); + } + } + return ts; + case 'x': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->fmt_offset += ctx->new_count; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->enc_packmode = ctx->new_packmode; + ++ts; + break; + case 'Z': + got_Z = 1; + ++ts; + if (*ts != 'f' && *ts != 'd' && *ts != 'g') { + __Pyx_BufFmt_RaiseUnexpectedChar('Z'); + return NULL; + } + CYTHON_FALLTHROUGH; + case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': + case 'l': case 'L': case 'q': case 'Q': + case 'f': case 'd': case 'g': + case 'O': case 'p': + if ((ctx->enc_type == *ts) && (got_Z == ctx->is_complex) && + (ctx->enc_packmode == ctx->new_packmode) && (!ctx->is_valid_array)) { + ctx->enc_count += ctx->new_count; + ctx->new_count = 1; + got_Z = 0; + ++ts; + break; + } + CYTHON_FALLTHROUGH; + case 's': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_count = ctx->new_count; + ctx->enc_packmode = ctx->new_packmode; + ctx->enc_type = *ts; + ctx->is_complex = got_Z; + ++ts; + ctx->new_count = 1; + got_Z = 0; + break; + case ':': + ++ts; + while(*ts != ':') ++ts; + ++ts; + break; + case '(': + if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL; + break; + default: + { + int number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return NULL; + ctx->new_count = (size_t)number; + } + } + } +} + +/* BufferGetAndValidate */ + static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { + if (unlikely(info->buf == NULL)) return; + if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; + __Pyx_ReleaseBuffer(info); +} +static void __Pyx_ZeroBuffer(Py_buffer* buf) { + buf->buf = NULL; + buf->obj = NULL; + buf->strides = __Pyx_zeros; + buf->shape = __Pyx_zeros; + buf->suboffsets = __Pyx_minusones; +} +static int __Pyx__GetBufferAndValidate( + Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, + int nd, int cast, __Pyx_BufFmt_StackElem* stack) +{ + buf->buf = NULL; + if (unlikely(__Pyx_GetBuffer(obj, buf, flags) == -1)) { + __Pyx_ZeroBuffer(buf); + return -1; + } + if (unlikely(buf->ndim != nd)) { + PyErr_Format(PyExc_ValueError, + "Buffer has wrong number of dimensions (expected %d, got %d)", + nd, buf->ndim); + goto fail; + } + if (!cast) { + __Pyx_BufFmt_Context ctx; + __Pyx_BufFmt_Init(&ctx, stack, dtype); + if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; + } + if (unlikely((size_t)buf->itemsize != dtype->size)) { + PyErr_Format(PyExc_ValueError, + "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", + buf->itemsize, (buf->itemsize > 1) ? "s" : "", + dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); + goto fail; + } + if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; + return 0; +fail:; + __Pyx_SafeReleaseBuffer(buf); + return -1; +} + +/* PyObjectGetAttrStr */ + #if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ + static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* PyDictVersioning */ + #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ + #if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* PyObjectCall */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = Py_TYPE(func)->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* ExtTypeTest */ + static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(__Pyx_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; +} + +/* GetItemInt */ + static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyList_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyTuple_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); + if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { + PyObject *r = PyList_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } + else if (PyTuple_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } else { + PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; + if (likely(m && m->sq_item)) { + if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { + Py_ssize_t l = m->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return NULL; + PyErr_Clear(); + } + } + return m->sq_item(o, i); + } + } +#else + if (is_list || PySequence_Check(o)) { + return PySequence_GetItem(o, i); + } +#endif + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +} + +/* ObjectGetItem */ + #if CYTHON_USE_TYPE_SLOTS +static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { + PyObject *runerr; + Py_ssize_t key_value; + PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; + if (unlikely(!(m && m->sq_item))) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); + return NULL; + } + key_value = __Pyx_PyIndex_AsSsize_t(index); + if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { + return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); + } + if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { + PyErr_Clear(); + PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); + } + return NULL; +} +static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { + PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; + if (likely(m && m->mp_subscript)) { + return m->mp_subscript(obj, key); + } + return __Pyx_PyObject_GetIndex(obj, key); +} +#endif + +/* PyFunctionFastCall */ + #if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyObjectCallMethO */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallNoArg */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, NULL, 0); + } +#endif +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) +#else + if (likely(PyCFunction_Check(func))) +#endif + { + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + +/* PyCFunctionFastCall */ + #if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyObjectCallOneArg */ + #if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (__Pyx_PyFastCFunction_Check(func)) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyObjectCall2Args */ + static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { + PyObject *args, *result = NULL; + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyFunction_FastCall(function, args, 2); + } + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(function)) { + PyObject *args[2] = {arg1, arg2}; + return __Pyx_PyCFunction_FastCall(function, args, 2); + } + #endif + args = PyTuple_New(2); + if (unlikely(!args)) goto done; + Py_INCREF(arg1); + PyTuple_SET_ITEM(args, 0, arg1); + Py_INCREF(arg2); + PyTuple_SET_ITEM(args, 1, arg2); + Py_INCREF(function); + result = __Pyx_PyObject_Call(function, args, NULL); + Py_DECREF(args); + Py_DECREF(function); +done: + return result; +} + +/* BufferIndexError */ + static void __Pyx_RaiseBufferIndexError(int axis) { + PyErr_Format(PyExc_IndexError, + "Out of bounds on buffer access (axis %d)", axis); +} + +/* BufferFallbackError */ + static void __Pyx_RaiseBufferFallbackError(void) { + PyErr_SetString(PyExc_ValueError, + "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!"); +} + +/* PyErrFetchRestore */ + #if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* GetTopmostException */ + #if CYTHON_USE_EXC_INFO_STACK +static _PyErr_StackItem * +__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) +{ + _PyErr_StackItem *exc_info = tstate->exc_info; + while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && + exc_info->previous_item != NULL) + { + exc_info = exc_info->previous_item; + } + return exc_info; +} +#endif + +/* SaveResetException */ + #if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); + *type = exc_info->exc_type; + *value = exc_info->exc_value; + *tb = exc_info->exc_traceback; + #else + *type = tstate->exc_type; + *value = tstate->exc_value; + *tb = tstate->exc_traceback; + #endif + Py_XINCREF(*type); + Py_XINCREF(*value); + Py_XINCREF(*tb); +} +static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + #if CYTHON_USE_EXC_INFO_STACK + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_traceback = tb; + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = type; + tstate->exc_value = value; + tstate->exc_traceback = tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +#endif + +/* PyErrExceptionMatches */ + #if CYTHON_FAST_THREAD_STATE +static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; icurexc_type; + if (exc_type == err) return 1; + if (unlikely(!exc_type)) return 0; + if (unlikely(PyTuple_Check(err))) + return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); + return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); +} +#endif + +/* GetException */ + #if CYTHON_FAST_THREAD_STATE +static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) +#else +static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) +#endif +{ + PyObject *local_type, *local_value, *local_tb; +#if CYTHON_FAST_THREAD_STATE + PyObject *tmp_type, *tmp_value, *tmp_tb; + local_type = tstate->curexc_type; + local_value = tstate->curexc_value; + local_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +#else + PyErr_Fetch(&local_type, &local_value, &local_tb); +#endif + PyErr_NormalizeException(&local_type, &local_value, &local_tb); +#if CYTHON_FAST_THREAD_STATE + if (unlikely(tstate->curexc_type)) +#else + if (unlikely(PyErr_Occurred())) +#endif + goto bad; + #if PY_MAJOR_VERSION >= 3 + if (local_tb) { + if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) + goto bad; + } + #endif + Py_XINCREF(local_tb); + Py_XINCREF(local_type); + Py_XINCREF(local_value); + *type = local_type; + *value = local_value; + *tb = local_tb; +#if CYTHON_FAST_THREAD_STATE + #if CYTHON_USE_EXC_INFO_STACK + { + _PyErr_StackItem *exc_info = tstate->exc_info; + tmp_type = exc_info->exc_type; + tmp_value = exc_info->exc_value; + tmp_tb = exc_info->exc_traceback; + exc_info->exc_type = local_type; + exc_info->exc_value = local_value; + exc_info->exc_traceback = local_tb; + } + #else + tmp_type = tstate->exc_type; + tmp_value = tstate->exc_value; + tmp_tb = tstate->exc_traceback; + tstate->exc_type = local_type; + tstate->exc_value = local_value; + tstate->exc_traceback = local_tb; + #endif + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +#else + PyErr_SetExcInfo(local_type, local_value, local_tb); +#endif + return 0; +bad: + *type = 0; + *value = 0; + *tb = 0; + Py_XDECREF(local_type); + Py_XDECREF(local_value); + Py_XDECREF(local_tb); + return -1; +} + +/* RaiseException */ + #if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, + CYTHON_UNUSED PyObject *cause) { + __Pyx_PyThreadState_declare + Py_XINCREF(type); + if (!value || value == Py_None) + value = NULL; + else + Py_INCREF(value); + if (!tb || tb == Py_None) + tb = NULL; + else { + Py_INCREF(tb); + if (!PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + } + if (PyType_Check(type)) { +#if CYTHON_COMPILING_IN_PYPY + if (!value) { + Py_INCREF(Py_None); + value = Py_None; + } +#endif + PyErr_NormalizeException(&type, &value, &tb); + } else { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + value = type; + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + } + __Pyx_PyThreadState_assign + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} +#else +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } + if (cause) { + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if CYTHON_COMPILING_IN_PYPY + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#else + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} +#endif + +/* TypeImport */ + #ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, + size_t size, enum __Pyx_ImportType_CheckSize check_size) +{ + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if ((size_t)basicsize < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* Import */ + static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + #if PY_MAJOR_VERSION < 3 + PyObject *py_import; + py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); + if (!py_import) + goto bad; + #endif + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + { + #if PY_MAJOR_VERSION >= 3 + if (level == -1) { + if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, 1); + if (!module) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + goto bad; + PyErr_Clear(); + } + } + level = 0; + } + #endif + if (!module) { + #if PY_MAJOR_VERSION < 3 + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, level); + #endif + } + } +bad: + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_import); + #endif + Py_XDECREF(empty_list); + Py_XDECREF(empty_dict); + return module; +} + +/* CLineInTraceback */ + #ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ + static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ + #include "compile.h" +#include "frameobject.h" +#include "traceback.h" +#if PY_VERSION_HEX >= 0x030b00a6 + #ifndef Py_BUILD_CORE + #define Py_BUILD_CORE 1 + #endif + #include "internal/pycore_frame.h" +#endif +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = NULL; + PyObject *py_funcname = NULL; + #if PY_MAJOR_VERSION < 3 + PyObject *py_srcfile = NULL; + py_srcfile = PyString_FromString(filename); + if (!py_srcfile) goto bad; + #endif + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + if (!py_funcname) goto bad; + funcname = PyUnicode_AsUTF8(py_funcname); + if (!funcname) goto bad; + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + if (!py_funcname) goto bad; + #endif + } + #if PY_MAJOR_VERSION < 3 + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + #else + py_code = PyCode_NewEmpty(filename, funcname, py_line); + #endif + Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline + return py_code; +bad: + Py_XDECREF(py_funcname); + #if PY_MAJOR_VERSION < 3 + Py_XDECREF(py_srcfile); + #endif + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject *ptype, *pvalue, *ptraceback; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) { + /* If the code object creation fails, then we should clear the + fetched exception references and propagate the new exception */ + Py_XDECREF(ptype); + Py_XDECREF(pvalue); + Py_XDECREF(ptraceback); + goto bad; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +#if PY_MAJOR_VERSION < 3 +static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { + if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); + PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name); + return -1; +} +static void __Pyx_ReleaseBuffer(Py_buffer *view) { + PyObject *obj = view->obj; + if (!obj) return; + if (PyObject_CheckBuffer(obj)) { + PyBuffer_Release(view); + return; + } + if ((0)) {} + view->obj = NULL; + Py_DECREF(obj); +} +#endif + + + /* CIntFromPyVerify */ + #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* Declarations */ + #if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return ::std::complex< float >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return x + y*(__pyx_t_float_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + __pyx_t_float_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +/* Arithmetic */ + #if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + #if 1 + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + if (b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); + } else if (fabsf(b.real) >= fabsf(b.imag)) { + if (b.real == 0 && b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); + } else { + float r = b.imag / b.real; + float s = (float)(1.0) / (b.real + b.imag * r); + return __pyx_t_float_complex_from_parts( + (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); + } + } else { + float r = b.real / b.imag; + float s = (float)(1.0) / (b.imag + b.real * r); + return __pyx_t_float_complex_from_parts( + (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); + } + } + #else + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + if (b.imag == 0) { + return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); + } else { + float denom = b.real * b.real + b.imag * b.imag; + return __pyx_t_float_complex_from_parts( + (a.real * b.real + a.imag * b.imag) / denom, + (a.imag * b.real - a.real * b.imag) / denom); + } + } + #endif + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrtf(z.real*z.real + z.imag*z.imag); + #else + return hypotf(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + float r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + float denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + return __Pyx_c_prod_float(a, a); + case 3: + z = __Pyx_c_prod_float(a, a); + return __Pyx_c_prod_float(z, a); + case 4: + z = __Pyx_c_prod_float(a, a); + return __Pyx_c_prod_float(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } else if (b.imag == 0) { + z.real = powf(a.real, b.real); + z.imag = 0; + return z; + } else if (a.real > 0) { + r = a.real; + theta = 0; + } else { + r = -a.real; + theta = atan2f(0.0, -1.0); + } + } else { + r = __Pyx_c_abs_float(a); + theta = atan2f(a.imag, a.real); + } + lnr = logf(r); + z_r = expf(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cosf(z_theta); + z.imag = z_r * sinf(z_theta); + return z; + } + #endif +#endif + +/* Declarations */ + #if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return ::std::complex< double >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return x + y*(__pyx_t_double_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + __pyx_t_double_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +/* Arithmetic */ + #if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + #if 1 + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + if (b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else if (fabs(b.real) >= fabs(b.imag)) { + if (b.real == 0 && b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); + } else { + double r = b.imag / b.real; + double s = (double)(1.0) / (b.real + b.imag * r); + return __pyx_t_double_complex_from_parts( + (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); + } + } else { + double r = b.real / b.imag; + double s = (double)(1.0) / (b.imag + b.real * r); + return __pyx_t_double_complex_from_parts( + (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); + } + } + #else + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + if (b.imag == 0) { + return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); + } else { + double denom = b.real * b.real + b.imag * b.imag; + return __pyx_t_double_complex_from_parts( + (a.real * b.real + a.imag * b.imag) / denom, + (a.imag * b.real - a.real * b.imag) / denom); + } + } + #endif + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrt(z.real*z.real + z.imag*z.imag); + #else + return hypot(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + double r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + double denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + return __Pyx_c_prod_double(a, a); + case 3: + z = __Pyx_c_prod_double(a, a); + return __Pyx_c_prod_double(z, a); + case 4: + z = __Pyx_c_prod_double(a, a); + return __Pyx_c_prod_double(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } else if (b.imag == 0) { + z.real = pow(a.real, b.real); + z.imag = 0; + return z; + } else if (a.real > 0) { + r = a.real; + theta = 0; + } else { + r = -a.real; + theta = atan2(0.0, -1.0); + } + } else { + r = __Pyx_c_abs_double(a); + theta = atan2(a.imag, a.real); + } + lnr = log(r); + z_r = exp(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cos(z_theta); + z.imag = z_r * sin(z_theta); + return z; + } + #endif +#endif + +/* CIntFromPy */ + static CYTHON_INLINE npy_int32 __Pyx_PyInt_As_npy_int32(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const npy_int32 neg_one = (npy_int32) -1, const_zero = (npy_int32) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(npy_int32) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (npy_int32) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (npy_int32) 0; + case 1: __PYX_VERIFY_RETURN_INT(npy_int32, digit, digits[0]) + case 2: + if (8 * sizeof(npy_int32) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) >= 2 * PyLong_SHIFT) { + return (npy_int32) (((((npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(npy_int32) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) >= 3 * PyLong_SHIFT) { + return (npy_int32) (((((((npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(npy_int32) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) >= 4 * PyLong_SHIFT) { + return (npy_int32) (((((((((npy_int32)digits[3]) << PyLong_SHIFT) | (npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (npy_int32) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(npy_int32) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(npy_int32) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (npy_int32) 0; + case -1: __PYX_VERIFY_RETURN_INT(npy_int32, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(npy_int32, digit, +digits[0]) + case -2: + if (8 * sizeof(npy_int32) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 2 * PyLong_SHIFT) { + return (npy_int32) (((npy_int32)-1)*(((((npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(npy_int32) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 2 * PyLong_SHIFT) { + return (npy_int32) ((((((npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(npy_int32) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 3 * PyLong_SHIFT) { + return (npy_int32) (((npy_int32)-1)*(((((((npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(npy_int32) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 3 * PyLong_SHIFT) { + return (npy_int32) ((((((((npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(npy_int32) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 4 * PyLong_SHIFT) { + return (npy_int32) (((npy_int32)-1)*(((((((((npy_int32)digits[3]) << PyLong_SHIFT) | (npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(npy_int32) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 4 * PyLong_SHIFT) { + return (npy_int32) ((((((((((npy_int32)digits[3]) << PyLong_SHIFT) | (npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + } +#endif + if (sizeof(npy_int32) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(npy_int32) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + npy_int32 val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (npy_int32) -1; + } + } else { + npy_int32 val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (npy_int32) -1; + val = __Pyx_PyInt_As_npy_int32(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to npy_int32"); + return (npy_int32) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to npy_int32"); + return (npy_int32) -1; +} + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + } +} + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* CIntFromPy */ + static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const long neg_one = (long) -1, const_zero = (long) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CIntFromPy */ + static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#endif + const int neg_one = (int) -1, const_zero = (int) 0; +#ifdef __Pyx_HAS_GCC_DIAGNOSTIC +#pragma GCC diagnostic pop +#endif + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* FastTypeChecks */ + #if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; i '9'); + break; + } + if (rt_from_call[i] != ctversion[i]) { + same = 0; + break; + } + } + if (!same) { + char rtversion[5] = {'\0'}; + char message[200]; + for (i=0; i<4; ++i) { + if (rt_from_call[i] == '.') { + if (found_dot) break; + found_dot = 1; + } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { + break; + } + rtversion[i] = rt_from_call[i]; + } + PyOS_snprintf(message, sizeof(message), + "compiletime version %s of module '%.100s' " + "does not match runtime version %s", + ctversion, __Pyx_MODULE_NAME, rtversion); + return PyErr_WarnEx(NULL, message, 1); + } + return 0; +} + +/* InitStrings */ + static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { + if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { + return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); +#if PY_MAJOR_VERSION < 3 + } else if (likely(PyInt_CheckExact(o))) { + return PyInt_AS_LONG(o); +#endif + } else { + Py_ssize_t ival; + PyObject *x; + x = PyNumber_Index(o); + if (!x) return -1; + ival = PyInt_AsLong(x); + Py_DECREF(x); + return ival; + } +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/easy_ViTPose/vit_utils/nms/gpu_nms.cpython-37m-x86_64-linux-gnu.so b/easy_ViTPose/vit_utils/nms/gpu_nms.cpython-37m-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..53f71fb79054668f902fbdb2f20ae4bdd0ee8689 Binary files /dev/null and b/easy_ViTPose/vit_utils/nms/gpu_nms.cpython-37m-x86_64-linux-gnu.so differ diff --git a/easy_ViTPose/vit_utils/nms/gpu_nms.cpython-39-x86_64-linux-gnu.so b/easy_ViTPose/vit_utils/nms/gpu_nms.cpython-39-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..c1ce043659f5cdc062091e2517f9ba74f8150738 Binary files /dev/null and b/easy_ViTPose/vit_utils/nms/gpu_nms.cpython-39-x86_64-linux-gnu.so differ diff --git a/easy_ViTPose/vit_utils/nms/gpu_nms.cu b/easy_ViTPose/vit_utils/nms/gpu_nms.cu new file mode 100644 index 0000000000000000000000000000000000000000..2f6931e1727db4ef68de4bf30a678ee570e80020 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/gpu_nms.cu @@ -0,0 +1,7080 @@ +// ------------------------------------------------------------------ +// Copyright (c) Microsoft +// Licensed under The MIT License +// Modified from MATLAB Faster R-CNN (https://github.com/shaoqingren/faster_rcnn) +// ------------------------------------------------------------------ + +//#include "gpu_nms.hpp" +#include +#include + + +#define CUDA_CHECK(condition) \ + /* Code block avoids redefinition of cudaError_t error */ \ + do { \ + cudaError_t error = condition; \ + if (error != cudaSuccess) { \ + std::cout << cudaGetErrorString(error) << std::endl; \ + } \ + } while (0) + +#define DIVUP(m,n) ((m) / (n) + ((m) % (n) > 0)) +int const threadsPerBlock = sizeof(unsigned long long) * 8; + +__device__ inline float devIoU(float const * const a, float const * const b) { + float left = max(a[0], b[0]), right = min(a[2], b[2]); + float top = max(a[1], b[1]), bottom = min(a[3], b[3]); + float width = max(right - left + 1, 0.f), height = max(bottom - top + 1, 0.f); + float interS = width * height; + float Sa = (a[2] - a[0] + 1) * (a[3] - a[1] + 1); + float Sb = (b[2] - b[0] + 1) * (b[3] - b[1] + 1); + return interS / (Sa + Sb - interS); +} + +__global__ void nms_kernel(const int n_boxes, const float nms_overlap_thresh, + const float *dev_boxes, unsigned long long *dev_mask) { + const int row_start = blockIdx.y; + const int col_start = blockIdx.x; + + // if (row_start > col_start) return; + + const int row_size = + min(n_boxes - row_start * threadsPerBlock, threadsPerBlock); + const int col_size = + min(n_boxes - col_start * threadsPerBlock, threadsPerBlock); + + __shared__ float block_boxes[threadsPerBlock * 5]; + if (threadIdx.x < col_size) { + block_boxes[threadIdx.x * 5 + 0] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 0]; + block_boxes[threadIdx.x * 5 + 1] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 1]; + block_boxes[threadIdx.x * 5 + 2] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 2]; + block_boxes[threadIdx.x * 5 + 3] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 3]; + block_boxes[threadIdx.x * 5 + 4] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 4]; + } + __syncthreads(); + + if (threadIdx.x < row_size) { + const int cur_box_idx = threadsPerBlock * row_start + threadIdx.x; + const float *cur_box = dev_boxes + cur_box_idx * 5; + int i = 0; + unsigned long long t = 0; + int start = 0; + if (row_start == col_start) { + start = threadIdx.x + 1; + } + for (i = start; i < col_size; i++) { + if (devIoU(cur_box, block_boxes + i * 5) > nms_overlap_thresh) { + t |= 1ULL << i; + } + } + const int col_blocks = DIVUP(n_boxes, threadsPerBlock); + dev_mask[cur_box_idx * col_blocks + col_start] = t; + } +} + +void _set_device(int device_id) { + int current_device; + CUDA_CHECK(cudaGetDevice(¤t_device)); + if (current_device == device_id) { + return; + } + // The call to cudaSetDevice must come before any calls to Get, which + // may perform initialization using the GPU. + CUDA_CHECK(cudaSetDevice(device_id)); +} + +void _nms(long* keep_out, int* num_out, const float* boxes_host, int boxes_num, + int boxes_dim, float nms_overlap_thresh, int device_id) { + _set_device(device_id); + + float* boxes_dev = NULL; + unsigned long long* mask_dev = NULL; + + const int col_blocks = DIVUP(boxes_num, threadsPerBlock); + + CUDA_CHECK(cudaMalloc(&boxes_dev, + boxes_num * boxes_dim * sizeof(float))); + CUDA_CHECK(cudaMemcpy(boxes_dev, + boxes_host, + boxes_num * boxes_dim * sizeof(float), + cudaMemcpyHostToDevice)); + + CUDA_CHECK(cudaMalloc(&mask_dev, + boxes_num * col_blocks * sizeof(unsigned long long))); + + dim3 blocks(DIVUP(boxes_num, threadsPerBlock), + DIVUP(boxes_num, threadsPerBlock)); + dim3 threads(threadsPerBlock); + nms_kernel<<>>(boxes_num, + nms_overlap_thresh, + boxes_dev, + mask_dev); + + std::vector mask_host(boxes_num * col_blocks); + CUDA_CHECK(cudaMemcpy(&mask_host[0], + mask_dev, + sizeof(unsigned long long) * boxes_num * col_blocks, + cudaMemcpyDeviceToHost)); + + std::vector remv(col_blocks); + memset(&remv[0], 0, sizeof(unsigned long long) * col_blocks); + + int num_to_keep = 0; + for (int i = 0; i < boxes_num; i++) { + int nblock = i / threadsPerBlock; + int inblock = i % threadsPerBlock; + + if (!(remv[nblock] & (1ULL << inblock))) { + keep_out[num_to_keep++] = i; + unsigned long long *p = &mask_host[0] + i * col_blocks; + for (int j = nblock; j < col_blocks; j++) { + remv[j] |= p[j]; + } + } + } + *num_out = num_to_keep; + + CUDA_CHECK(cudaFree(boxes_dev)); + CUDA_CHECK(cudaFree(mask_dev)); +} + + + + + + + + + + +/* Generated by Cython 0.24 */ + +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03020000) + #error Cython requires Python 2.6+ or Python 3.2+. +#else +#define CYTHON_ABI "0_24" +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 +#endif +#if !defined(CYTHON_USE_PYLONG_INTERNALS) && CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02070000 + #define CYTHON_USE_PYLONG_INTERNALS 1 +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #include "longintrepr.h" + #undef SHIFT + #undef BASE + #undef MASK +#endif +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) +#else + #define CYTHON_PEP393_ENABLED 0 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t PyInt_AsLong +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if PY_VERSION_HEX >= 0x030500B1 +#define __Pyx_PyAsyncMethodsStruct PyAsyncMethods +#define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) +#elif CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 +typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; +} __Pyx_PyAsyncMethodsStruct; +#define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) +#else +#define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) + +#ifndef __cplusplus + #error "Cython files generated with the C++ option must be compiled with a C++ compiler." +#endif +#ifndef CYTHON_INLINE + #define CYTHON_INLINE inline +#endif +template +void __Pyx_call_destructor(T& x) { + x.~T(); +} +template +class __Pyx_FakeReference { + public: + __Pyx_FakeReference() : ptr(NULL) { } + __Pyx_FakeReference(const T& ref) : ptr(const_cast(&ref)) { } + T *operator->() { return ptr; } + operator T&() { return *ptr; } + private: + T *ptr; +}; + +#if defined(WIN32) || defined(MS_WINDOWS) + #define _USE_MATH_DEFINES +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif + + +#define __PYX_ERR(f_index, lineno, Ln_error) \ +{ \ + __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ +} + +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__nms__gpu_nms +#define __PYX_HAVE_API__nms__gpu_nms +#include "string.h" +#include "stdio.h" +#include "stdlib.h" +#include "numpy/arrayobject.h" +#include "numpy/ufuncobject.h" +#include "gpu_nms.hpp" +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#ifdef PYREX_WITHOUT_ASSERTIONS +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0 +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) && defined (_M_X64) + #define __Pyx_sst_abs(value) _abs64(value) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyObject_AsSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +#if PY_MAJOR_VERSION < 3 +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) +{ + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#else +#define __Pyx_Py_UNICODE_strlen Py_UNICODE_strlen +#endif +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +#define __Pyx_PyBool_FromLong(b) ((b) ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False)) +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +#if CYTHON_COMPILING_IN_CPYTHON +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c)); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ + +static PyObject *__pyx_m; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + +/* None.proto */ +#if !defined(CYTHON_CCOMPLEX) + #if defined(__cplusplus) + #define CYTHON_CCOMPLEX 1 + #elif defined(_Complex_I) + #define CYTHON_CCOMPLEX 1 + #else + #define CYTHON_CCOMPLEX 0 + #endif +#endif +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #include + #else + #include + #endif +#endif +#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) + #undef _Complex_I + #define _Complex_I 1.0fj +#endif + + +static const char *__pyx_f[] = { + "nms\\gpu_nms.pyx", + "__init__.pxd", + "type.pxd", +}; +/* BufferFormatStructs.proto */ +#define IS_UNSIGNED(type) (((type) -1) > 0) +struct __Pyx_StructField_; +#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) +typedef struct { + const char* name; + struct __Pyx_StructField_* fields; + size_t size; + size_t arraysize[8]; + int ndim; + char typegroup; + char is_unsigned; + int flags; +} __Pyx_TypeInfo; +typedef struct __Pyx_StructField_ { + __Pyx_TypeInfo* type; + const char* name; + size_t offset; +} __Pyx_StructField; +typedef struct { + __Pyx_StructField* field; + size_t parent_offset; +} __Pyx_BufFmt_StackElem; +typedef struct { + __Pyx_StructField root; + __Pyx_BufFmt_StackElem* head; + size_t fmt_offset; + size_t new_count, enc_count; + size_t struct_alignment; + int is_complex; + char enc_type; + char new_packmode; + char enc_packmode; + char is_valid_array; +} __Pyx_BufFmt_Context; + + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":725 + * # in Cython to enable them only on the right systems. + * + * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t + */ +typedef npy_int8 __pyx_t_5numpy_int8_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":726 + * + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t + */ +typedef npy_int16 __pyx_t_5numpy_int16_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":727 + * ctypedef npy_int8 int8_t + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< + * ctypedef npy_int64 int64_t + * #ctypedef npy_int96 int96_t + */ +typedef npy_int32 __pyx_t_5numpy_int32_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":728 + * ctypedef npy_int16 int16_t + * ctypedef npy_int32 int32_t + * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< + * #ctypedef npy_int96 int96_t + * #ctypedef npy_int128 int128_t + */ +typedef npy_int64 __pyx_t_5numpy_int64_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":732 + * #ctypedef npy_int128 int128_t + * + * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t + */ +typedef npy_uint8 __pyx_t_5numpy_uint8_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":733 + * + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t + */ +typedef npy_uint16 __pyx_t_5numpy_uint16_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":734 + * ctypedef npy_uint8 uint8_t + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< + * ctypedef npy_uint64 uint64_t + * #ctypedef npy_uint96 uint96_t + */ +typedef npy_uint32 __pyx_t_5numpy_uint32_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":735 + * ctypedef npy_uint16 uint16_t + * ctypedef npy_uint32 uint32_t + * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< + * #ctypedef npy_uint96 uint96_t + * #ctypedef npy_uint128 uint128_t + */ +typedef npy_uint64 __pyx_t_5numpy_uint64_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":739 + * #ctypedef npy_uint128 uint128_t + * + * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< + * ctypedef npy_float64 float64_t + * #ctypedef npy_float80 float80_t + */ +typedef npy_float32 __pyx_t_5numpy_float32_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":740 + * + * ctypedef npy_float32 float32_t + * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< + * #ctypedef npy_float80 float80_t + * #ctypedef npy_float128 float128_t + */ +typedef npy_float64 __pyx_t_5numpy_float64_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":749 + * # The int types are mapped a bit surprising -- + * # numpy.int corresponds to 'l' and numpy.long to 'q' + * ctypedef npy_long int_t # <<<<<<<<<<<<<< + * ctypedef npy_longlong long_t + * ctypedef npy_longlong longlong_t + */ +typedef npy_long __pyx_t_5numpy_int_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":750 + * # numpy.int corresponds to 'l' and numpy.long to 'q' + * ctypedef npy_long int_t + * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< + * ctypedef npy_longlong longlong_t + * + */ +typedef npy_longlong __pyx_t_5numpy_long_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":751 + * ctypedef npy_long int_t + * ctypedef npy_longlong long_t + * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< + * + * ctypedef npy_ulong uint_t + */ +typedef npy_longlong __pyx_t_5numpy_longlong_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":753 + * ctypedef npy_longlong longlong_t + * + * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< + * ctypedef npy_ulonglong ulong_t + * ctypedef npy_ulonglong ulonglong_t + */ +typedef npy_ulong __pyx_t_5numpy_uint_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":754 + * + * ctypedef npy_ulong uint_t + * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< + * ctypedef npy_ulonglong ulonglong_t + * + */ +typedef npy_ulonglong __pyx_t_5numpy_ulong_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":755 + * ctypedef npy_ulong uint_t + * ctypedef npy_ulonglong ulong_t + * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< + * + * ctypedef npy_intp intp_t + */ +typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":757 + * ctypedef npy_ulonglong ulonglong_t + * + * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< + * ctypedef npy_uintp uintp_t + * + */ +typedef npy_intp __pyx_t_5numpy_intp_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":758 + * + * ctypedef npy_intp intp_t + * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< + * + * ctypedef npy_double float_t + */ +typedef npy_uintp __pyx_t_5numpy_uintp_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":760 + * ctypedef npy_uintp uintp_t + * + * ctypedef npy_double float_t # <<<<<<<<<<<<<< + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t + */ +typedef npy_double __pyx_t_5numpy_float_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":761 + * + * ctypedef npy_double float_t + * ctypedef npy_double double_t # <<<<<<<<<<<<<< + * ctypedef npy_longdouble longdouble_t + * + */ +typedef npy_double __pyx_t_5numpy_double_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":762 + * ctypedef npy_double float_t + * ctypedef npy_double double_t + * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< + * + * ctypedef npy_cfloat cfloat_t + */ +typedef npy_longdouble __pyx_t_5numpy_longdouble_t; +/* None.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< float > __pyx_t_float_complex; + #else + typedef float _Complex __pyx_t_float_complex; + #endif +#else + typedef struct { float real, imag; } __pyx_t_float_complex; +#endif + +/* None.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + typedef ::std::complex< double > __pyx_t_double_complex; + #else + typedef double _Complex __pyx_t_double_complex; + #endif +#else + typedef struct { double real, imag; } __pyx_t_double_complex; +#endif + + +/*--- Type declarations ---*/ + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":764 + * ctypedef npy_longdouble longdouble_t + * + * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< + * ctypedef npy_cdouble cdouble_t + * ctypedef npy_clongdouble clongdouble_t + */ +typedef npy_cfloat __pyx_t_5numpy_cfloat_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":765 + * + * ctypedef npy_cfloat cfloat_t + * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< + * ctypedef npy_clongdouble clongdouble_t + * + */ +typedef npy_cdouble __pyx_t_5numpy_cdouble_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":766 + * ctypedef npy_cfloat cfloat_t + * ctypedef npy_cdouble cdouble_t + * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< + * + * ctypedef npy_cdouble complex_t + */ +typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":768 + * ctypedef npy_clongdouble clongdouble_t + * + * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew1(a): + */ +typedef npy_cdouble __pyx_t_5numpy_complex_t; + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* ArgTypeTest.proto */ +static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact); + +/* BufferFormatCheck.proto */ +static CYTHON_INLINE int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, + __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type); // PROTO + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* GetModuleGlobalName.proto */ +static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name); + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* ExtTypeTest.proto */ +static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* BufferIndexError.proto */ +static void __Pyx_RaiseBufferIndexError(int axis); + +#define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0) +#define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1) +/* SliceObject.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice( + PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** py_start, PyObject** py_stop, PyObject** py_slice, + int has_cstart, int has_cstop, int wraparound); + +/* BufferFallbackError.proto */ +static void __Pyx_RaiseBufferFallbackError(void); + +/* PyThreadStateGet.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = PyThreadState_GET(); +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#else +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* RaiseException.proto */ +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); + +/* DictGetItem.proto */ +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY +static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { + PyObject *value; + value = PyDict_GetItemWithError(d, key); + if (unlikely(!value)) { + if (!PyErr_Occurred()) { + PyObject* args = PyTuple_Pack(1, key); + if (likely(args)) + PyErr_SetObject(PyExc_KeyError, args); + Py_XDECREF(args); + } + return NULL; + } + Py_INCREF(value); + return value; +} +#else + #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) +#endif + +/* RaiseTooManyValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); + +/* RaiseNeedMoreValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +/* RaiseNoneIterError.proto */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); + +/* Import.proto */ +static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* BufferStructDeclare.proto */ +typedef struct { + Py_ssize_t shape, strides, suboffsets; +} __Pyx_Buf_DimInfo; +typedef struct { + size_t refcount; + Py_buffer pybuffer; +} __Pyx_Buffer; +typedef struct { + __Pyx_Buffer *rcbuffer; + char *data; + __Pyx_Buf_DimInfo diminfo[8]; +} __Pyx_LocalBuf_ND; + +#if PY_MAJOR_VERSION < 3 + static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); + static void __Pyx_ReleaseBuffer(Py_buffer *view); +#else + #define __Pyx_GetBuffer PyObject_GetBuffer + #define __Pyx_ReleaseBuffer PyBuffer_Release +#endif + + +/* None.proto */ +static Py_ssize_t __Pyx_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0}; +static Py_ssize_t __Pyx_minusones[] = {-1, -1, -1, -1, -1, -1, -1, -1}; + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); + +/* None.proto */ +#if CYTHON_CCOMPLEX + #ifdef __cplusplus + #define __Pyx_CREAL(z) ((z).real()) + #define __Pyx_CIMAG(z) ((z).imag()) + #else + #define __Pyx_CREAL(z) (__real__(z)) + #define __Pyx_CIMAG(z) (__imag__(z)) + #endif +#else + #define __Pyx_CREAL(z) ((z).real) + #define __Pyx_CIMAG(z) ((z).imag) +#endif +#if defined(__cplusplus) && CYTHON_CCOMPLEX && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) + #define __Pyx_SET_CREAL(z,x) ((z).real(x)) + #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) +#else + #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) + #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) +#endif + +/* None.proto */ +static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); + +/* None.proto */ +#if CYTHON_CCOMPLEX + #define __Pyx_c_eqf(a, b) ((a)==(b)) + #define __Pyx_c_sumf(a, b) ((a)+(b)) + #define __Pyx_c_difff(a, b) ((a)-(b)) + #define __Pyx_c_prodf(a, b) ((a)*(b)) + #define __Pyx_c_quotf(a, b) ((a)/(b)) + #define __Pyx_c_negf(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zerof(z) ((z)==(float)0) + #define __Pyx_c_conjf(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_absf(z) (::std::abs(z)) + #define __Pyx_c_powf(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zerof(z) ((z)==0) + #define __Pyx_c_conjf(z) (conjf(z)) + #if 1 + #define __Pyx_c_absf(z) (cabsf(z)) + #define __Pyx_c_powf(a, b) (cpowf(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex, __pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex); + static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex); + #if 1 + static CYTHON_INLINE float __Pyx_c_absf(__pyx_t_float_complex); + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_powf(__pyx_t_float_complex, __pyx_t_float_complex); + #endif +#endif + +/* None.proto */ +static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); + +/* None.proto */ +#if CYTHON_CCOMPLEX + #define __Pyx_c_eq(a, b) ((a)==(b)) + #define __Pyx_c_sum(a, b) ((a)+(b)) + #define __Pyx_c_diff(a, b) ((a)-(b)) + #define __Pyx_c_prod(a, b) ((a)*(b)) + #define __Pyx_c_quot(a, b) ((a)/(b)) + #define __Pyx_c_neg(a) (-(a)) + #ifdef __cplusplus + #define __Pyx_c_is_zero(z) ((z)==(double)0) + #define __Pyx_c_conj(z) (::std::conj(z)) + #if 1 + #define __Pyx_c_abs(z) (::std::abs(z)) + #define __Pyx_c_pow(a, b) (::std::pow(a, b)) + #endif + #else + #define __Pyx_c_is_zero(z) ((z)==0) + #define __Pyx_c_conj(z) (conj(z)) + #if 1 + #define __Pyx_c_abs(z) (cabs(z)) + #define __Pyx_c_pow(a, b) (cpow(a, b)) + #endif + #endif +#else + static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex, __pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex); + static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex); + #if 1 + static CYTHON_INLINE double __Pyx_c_abs(__pyx_t_double_complex); + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow(__pyx_t_double_complex, __pyx_t_double_complex); + #endif +#endif + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE npy_int32 __Pyx_PyInt_As_npy_int32(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* PyIdentifierFromString.proto */ +#if !defined(__Pyx_PyIdentifier_FromString) +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s) +#else + #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s) +#endif +#endif + +/* ModuleImport.proto */ +static PyObject *__Pyx_ImportModule(const char *name); + +/* TypeImport.proto */ +static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + +/* Module declarations from 'cpython.buffer' */ + +/* Module declarations from 'libc.string' */ + +/* Module declarations from 'libc.stdio' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.type' */ +static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; + +/* Module declarations from 'cpython' */ + +/* Module declarations from 'cpython.object' */ + +/* Module declarations from 'cpython.ref' */ + +/* Module declarations from 'libc.stdlib' */ + +/* Module declarations from 'numpy' */ + +/* Module declarations from 'numpy' */ +static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; +static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; +static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; +static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; +static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; +static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, char *, char *, int *); /*proto*/ + +/* Module declarations from 'nms.gpu_nms' */ +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t = { "float32_t", NULL, sizeof(__pyx_t_5numpy_float32_t), { 0 }, 0, 'R', 0, 0 }; +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t = { "int32_t", NULL, sizeof(__pyx_t_5numpy_int32_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_int32_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_int32_t), 0 }; +static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_intp_t = { "intp_t", NULL, sizeof(__pyx_t_5numpy_intp_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_intp_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_intp_t), 0 }; +#define __Pyx_MODULE_NAME "nms.gpu_nms" +int __pyx_module_is_main_nms__gpu_nms = 0; + +/* Implementation of 'nms.gpu_nms' */ +static PyObject *__pyx_builtin_ValueError; +static PyObject *__pyx_builtin_range; +static PyObject *__pyx_builtin_RuntimeError; +static const char __pyx_k_np[] = "np"; +static const char __pyx_k_dets[] = "dets"; +static const char __pyx_k_keep[] = "keep"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_dtype[] = "dtype"; +static const char __pyx_k_int32[] = "int32"; +static const char __pyx_k_numpy[] = "numpy"; +static const char __pyx_k_order[] = "order"; +static const char __pyx_k_range[] = "range"; +static const char __pyx_k_zeros[] = "zeros"; +static const char __pyx_k_import[] = "__import__"; +static const char __pyx_k_scores[] = "scores"; +static const char __pyx_k_thresh[] = "thresh"; +static const char __pyx_k_argsort[] = "argsort"; +static const char __pyx_k_gpu_nms[] = "gpu_nms"; +static const char __pyx_k_num_out[] = "num_out"; +static const char __pyx_k_boxes_dim[] = "boxes_dim"; +static const char __pyx_k_boxes_num[] = "boxes_num"; +static const char __pyx_k_device_id[] = "device_id"; +static const char __pyx_k_ValueError[] = "ValueError"; +static const char __pyx_k_nms_gpu_nms[] = "nms.gpu_nms"; +static const char __pyx_k_sorted_dets[] = "sorted_dets"; +static const char __pyx_k_RuntimeError[] = "RuntimeError"; +static const char __pyx_k_ndarray_is_not_C_contiguous[] = "ndarray is not C contiguous"; +static const char __pyx_k_unknown_dtype_code_in_numpy_pxd[] = "unknown dtype code in numpy.pxd (%d)"; +static const char __pyx_k_D_v_zix_caffe_caffe_win_20160523[] = "D:\\v-zix\\caffe\\caffe-win-20160523\\models\\py-faster-rcnn-windows\\lib\\nms\\gpu_nms.pyx"; +static const char __pyx_k_Format_string_allocated_too_shor[] = "Format string allocated too short, see comment in numpy.pxd"; +static const char __pyx_k_Non_native_byte_order_not_suppor[] = "Non-native byte order not supported"; +static const char __pyx_k_ndarray_is_not_Fortran_contiguou[] = "ndarray is not Fortran contiguous"; +static const char __pyx_k_Format_string_allocated_too_shor_2[] = "Format string allocated too short."; +static PyObject *__pyx_kp_s_D_v_zix_caffe_caffe_win_20160523; +static PyObject *__pyx_kp_u_Format_string_allocated_too_shor; +static PyObject *__pyx_kp_u_Format_string_allocated_too_shor_2; +static PyObject *__pyx_kp_u_Non_native_byte_order_not_suppor; +static PyObject *__pyx_n_s_RuntimeError; +static PyObject *__pyx_n_s_ValueError; +static PyObject *__pyx_n_s_argsort; +static PyObject *__pyx_n_s_boxes_dim; +static PyObject *__pyx_n_s_boxes_num; +static PyObject *__pyx_n_s_dets; +static PyObject *__pyx_n_s_device_id; +static PyObject *__pyx_n_s_dtype; +static PyObject *__pyx_n_s_gpu_nms; +static PyObject *__pyx_n_s_import; +static PyObject *__pyx_n_s_int32; +static PyObject *__pyx_n_s_keep; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_kp_u_ndarray_is_not_C_contiguous; +static PyObject *__pyx_kp_u_ndarray_is_not_Fortran_contiguou; +static PyObject *__pyx_n_s_nms_gpu_nms; +static PyObject *__pyx_n_s_np; +static PyObject *__pyx_n_s_num_out; +static PyObject *__pyx_n_s_numpy; +static PyObject *__pyx_n_s_order; +static PyObject *__pyx_n_s_range; +static PyObject *__pyx_n_s_scores; +static PyObject *__pyx_n_s_sorted_dets; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_n_s_thresh; +static PyObject *__pyx_kp_u_unknown_dtype_code_in_numpy_pxd; +static PyObject *__pyx_n_s_zeros; +static PyObject *__pyx_pf_3nms_7gpu_nms_gpu_nms(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_dets, PyObject *__pyx_v_thresh, __pyx_t_5numpy_int32_t __pyx_v_device_id); /* proto */ +static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ +static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */ +static PyObject *__pyx_int_4; +static PyObject *__pyx_int_neg_1; +static PyObject *__pyx_slice_; +static PyObject *__pyx_slice__3; +static PyObject *__pyx_slice__4; +static PyObject *__pyx_tuple__2; +static PyObject *__pyx_tuple__5; +static PyObject *__pyx_tuple__6; +static PyObject *__pyx_tuple__7; +static PyObject *__pyx_tuple__8; +static PyObject *__pyx_tuple__9; +static PyObject *__pyx_tuple__10; +static PyObject *__pyx_tuple__11; +static PyObject *__pyx_codeobj__12; + +/* "nms/gpu_nms.pyx":16 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_3nms_7gpu_nms_1gpu_nms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_3nms_7gpu_nms_1gpu_nms = {"gpu_nms", (PyCFunction)__pyx_pw_3nms_7gpu_nms_1gpu_nms, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_3nms_7gpu_nms_1gpu_nms(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyArrayObject *__pyx_v_dets = 0; + PyObject *__pyx_v_thresh = 0; + __pyx_t_5numpy_int32_t __pyx_v_device_id; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("gpu_nms (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_dets,&__pyx_n_s_thresh,&__pyx_n_s_device_id,0}; + PyObject* values[3] = {0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_dets)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + case 1: + if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_thresh)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("gpu_nms", 0, 2, 3, 1); __PYX_ERR(0, 16, __pyx_L3_error) + } + case 2: + if (kw_args > 0) { + PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_device_id); + if (value) { values[2] = value; kw_args--; } + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "gpu_nms") < 0)) __PYX_ERR(0, 16, __pyx_L3_error) + } + } else { + switch (PyTuple_GET_SIZE(__pyx_args)) { + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + break; + default: goto __pyx_L5_argtuple_error; + } + } + __pyx_v_dets = ((PyArrayObject *)values[0]); + __pyx_v_thresh = ((PyObject*)values[1]); + if (values[2]) { + __pyx_v_device_id = __Pyx_PyInt_As_npy_int32(values[2]); if (unlikely((__pyx_v_device_id == (npy_int32)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L3_error) + } else { + __pyx_v_device_id = ((__pyx_t_5numpy_int32_t)0); + } + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("gpu_nms", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 16, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("nms.gpu_nms.gpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_dets), __pyx_ptype_5numpy_ndarray, 1, "dets", 0))) __PYX_ERR(0, 16, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_thresh), (&PyFloat_Type), 1, "thresh", 1))) __PYX_ERR(0, 16, __pyx_L1_error) + __pyx_r = __pyx_pf_3nms_7gpu_nms_gpu_nms(__pyx_self, __pyx_v_dets, __pyx_v_thresh, __pyx_v_device_id); + + /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_3nms_7gpu_nms_gpu_nms(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_dets, PyObject *__pyx_v_thresh, __pyx_t_5numpy_int32_t __pyx_v_device_id) { + int __pyx_v_boxes_num; + int __pyx_v_boxes_dim; + int __pyx_v_num_out; + PyArrayObject *__pyx_v_keep = 0; + PyArrayObject *__pyx_v_scores = 0; + PyArrayObject *__pyx_v_order = 0; + PyArrayObject *__pyx_v_sorted_dets = 0; + __Pyx_LocalBuf_ND __pyx_pybuffernd_dets; + __Pyx_Buffer __pyx_pybuffer_dets; + __Pyx_LocalBuf_ND __pyx_pybuffernd_keep; + __Pyx_Buffer __pyx_pybuffer_keep; + __Pyx_LocalBuf_ND __pyx_pybuffernd_order; + __Pyx_Buffer __pyx_pybuffer_order; + __Pyx_LocalBuf_ND __pyx_pybuffernd_scores; + __Pyx_Buffer __pyx_pybuffer_scores; + __Pyx_LocalBuf_ND __pyx_pybuffernd_sorted_dets; + __Pyx_Buffer __pyx_pybuffer_sorted_dets; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyArrayObject *__pyx_t_6 = NULL; + PyArrayObject *__pyx_t_7 = NULL; + PyArrayObject *__pyx_t_8 = NULL; + PyArrayObject *__pyx_t_9 = NULL; + Py_ssize_t __pyx_t_10; + int __pyx_t_11; + Py_ssize_t __pyx_t_12; + Py_ssize_t __pyx_t_13; + float __pyx_t_14; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + __Pyx_RefNannySetupContext("gpu_nms", 0); + __pyx_pybuffer_keep.pybuffer.buf = NULL; + __pyx_pybuffer_keep.refcount = 0; + __pyx_pybuffernd_keep.data = NULL; + __pyx_pybuffernd_keep.rcbuffer = &__pyx_pybuffer_keep; + __pyx_pybuffer_scores.pybuffer.buf = NULL; + __pyx_pybuffer_scores.refcount = 0; + __pyx_pybuffernd_scores.data = NULL; + __pyx_pybuffernd_scores.rcbuffer = &__pyx_pybuffer_scores; + __pyx_pybuffer_order.pybuffer.buf = NULL; + __pyx_pybuffer_order.refcount = 0; + __pyx_pybuffernd_order.data = NULL; + __pyx_pybuffernd_order.rcbuffer = &__pyx_pybuffer_order; + __pyx_pybuffer_sorted_dets.pybuffer.buf = NULL; + __pyx_pybuffer_sorted_dets.refcount = 0; + __pyx_pybuffernd_sorted_dets.data = NULL; + __pyx_pybuffernd_sorted_dets.rcbuffer = &__pyx_pybuffer_sorted_dets; + __pyx_pybuffer_dets.pybuffer.buf = NULL; + __pyx_pybuffer_dets.refcount = 0; + __pyx_pybuffernd_dets.data = NULL; + __pyx_pybuffernd_dets.rcbuffer = &__pyx_pybuffer_dets; + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dets.rcbuffer->pybuffer, (PyObject*)__pyx_v_dets, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) __PYX_ERR(0, 16, __pyx_L1_error) + } + __pyx_pybuffernd_dets.diminfo[0].strides = __pyx_pybuffernd_dets.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_dets.diminfo[0].shape = __pyx_pybuffernd_dets.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_dets.diminfo[1].strides = __pyx_pybuffernd_dets.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_dets.diminfo[1].shape = __pyx_pybuffernd_dets.rcbuffer->pybuffer.shape[1]; + + /* "nms/gpu_nms.pyx":18 + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] # <<<<<<<<<<<<<< + * cdef int boxes_dim = dets.shape[1] + * cdef int num_out + */ + __pyx_v_boxes_num = (__pyx_v_dets->dimensions[0]); + + /* "nms/gpu_nms.pyx":19 + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + * cdef int boxes_dim = dets.shape[1] # <<<<<<<<<<<<<< + * cdef int num_out + * cdef np.ndarray[np.int32_t, ndim=1] \ + */ + __pyx_v_boxes_dim = (__pyx_v_dets->dimensions[1]); + + /* "nms/gpu_nms.pyx":22 + * cdef int num_out + * cdef np.ndarray[np.int32_t, ndim=1] \ + * keep = np.zeros(boxes_num, dtype=np.int32) # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=1] \ + * scores = dets[:, 4] + */ + __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_boxes_num); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); + __pyx_t_1 = 0; + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_int32); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_5) < 0) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 22, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 22, __pyx_L1_error) + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_keep.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_keep = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_keep.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 21, __pyx_L1_error) + } else {__pyx_pybuffernd_keep.diminfo[0].strides = __pyx_pybuffernd_keep.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_keep.diminfo[0].shape = __pyx_pybuffernd_keep.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_6 = 0; + __pyx_v_keep = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + /* "nms/gpu_nms.pyx":24 + * keep = np.zeros(boxes_num, dtype=np.int32) + * cdef np.ndarray[np.float32_t, ndim=1] \ + * scores = dets[:, 4] # <<<<<<<<<<<<<< + * #cdef np.ndarray[np.int_t, ndim=1] \ // 20160601, by xzn + * # order = scores.argsort()[::-1] + */ + __pyx_t_5 = PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_tuple__2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 24, __pyx_L1_error) + __pyx_t_7 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_scores.rcbuffer->pybuffer, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_scores = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_scores.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 23, __pyx_L1_error) + } else {__pyx_pybuffernd_scores.diminfo[0].strides = __pyx_pybuffernd_scores.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_scores.diminfo[0].shape = __pyx_pybuffernd_scores.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_7 = 0; + __pyx_v_scores = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + /* "nms/gpu_nms.pyx":28 + * # order = scores.argsort()[::-1] + * cdef np.ndarray[np.intp_t, ndim=1] \ + * order = scores.argsort()[::-1] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] + */ + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_scores), __pyx_n_s_argsort); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = NULL; + if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_1, function); + } + } + if (__pyx_t_3) { + __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else { + __pyx_t_5 = __Pyx_PyObject_CallNoArg(__pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 28, __pyx_L1_error) + } + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyObject_GetItem(__pyx_t_5, __pyx_slice__3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 28, __pyx_L1_error) + __pyx_t_8 = ((PyArrayObject *)__pyx_t_1); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_order.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_5numpy_intp_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + __pyx_v_order = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_order.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 27, __pyx_L1_error) + } else {__pyx_pybuffernd_order.diminfo[0].strides = __pyx_pybuffernd_order.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_order.diminfo[0].shape = __pyx_pybuffernd_order.rcbuffer->pybuffer.shape[0]; + } + } + __pyx_t_8 = 0; + __pyx_v_order = ((PyArrayObject *)__pyx_t_1); + __pyx_t_1 = 0; + + /* "nms/gpu_nms.pyx":30 + * order = scores.argsort()[::-1] + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] # <<<<<<<<<<<<<< + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + * keep = keep[:num_out] + */ + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 30, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(((PyObject *)__pyx_v_order)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_order)); + PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_order)); + __Pyx_INCREF(__pyx_slice__4); + __Pyx_GIVEREF(__pyx_slice__4); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_slice__4); + __pyx_t_5 = PyObject_GetItem(((PyObject *)__pyx_v_dets), __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 30, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 30, __pyx_L1_error) + __pyx_t_9 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer, (PyObject*)__pyx_t_9, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) { + __pyx_v_sorted_dets = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.buf = NULL; + __PYX_ERR(0, 29, __pyx_L1_error) + } else {__pyx_pybuffernd_sorted_dets.diminfo[0].strides = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_sorted_dets.diminfo[0].shape = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_sorted_dets.diminfo[1].strides = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_sorted_dets.diminfo[1].shape = __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.shape[1]; + } + } + __pyx_t_9 = 0; + __pyx_v_sorted_dets = ((PyArrayObject *)__pyx_t_5); + __pyx_t_5 = 0; + + /* "nms/gpu_nms.pyx":31 + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) # <<<<<<<<<<<<<< + * keep = keep[:num_out] + * return list(order[keep]) + */ + __pyx_t_10 = 0; + __pyx_t_11 = -1; + if (__pyx_t_10 < 0) { + __pyx_t_10 += __pyx_pybuffernd_keep.diminfo[0].shape; + if (unlikely(__pyx_t_10 < 0)) __pyx_t_11 = 0; + } else if (unlikely(__pyx_t_10 >= __pyx_pybuffernd_keep.diminfo[0].shape)) __pyx_t_11 = 0; + if (unlikely(__pyx_t_11 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_11); + __PYX_ERR(0, 31, __pyx_L1_error) + } + __pyx_t_12 = 0; + __pyx_t_13 = 0; + __pyx_t_11 = -1; + if (__pyx_t_12 < 0) { + __pyx_t_12 += __pyx_pybuffernd_sorted_dets.diminfo[0].shape; + if (unlikely(__pyx_t_12 < 0)) __pyx_t_11 = 0; + } else if (unlikely(__pyx_t_12 >= __pyx_pybuffernd_sorted_dets.diminfo[0].shape)) __pyx_t_11 = 0; + if (__pyx_t_13 < 0) { + __pyx_t_13 += __pyx_pybuffernd_sorted_dets.diminfo[1].shape; + if (unlikely(__pyx_t_13 < 0)) __pyx_t_11 = 1; + } else if (unlikely(__pyx_t_13 >= __pyx_pybuffernd_sorted_dets.diminfo[1].shape)) __pyx_t_11 = 1; + if (unlikely(__pyx_t_11 != -1)) { + __Pyx_RaiseBufferIndexError(__pyx_t_11); + __PYX_ERR(0, 31, __pyx_L1_error) + } + __pyx_t_14 = __pyx_PyFloat_AsFloat(__pyx_v_thresh); if (unlikely((__pyx_t_14 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 31, __pyx_L1_error) + _nms((&(*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_int32_t *, __pyx_pybuffernd_keep.rcbuffer->pybuffer.buf, __pyx_t_10, __pyx_pybuffernd_keep.diminfo[0].strides))), (&__pyx_v_num_out), (&(*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_float32_t *, __pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_sorted_dets.diminfo[0].strides, __pyx_t_13, __pyx_pybuffernd_sorted_dets.diminfo[1].strides))), __pyx_v_boxes_num, __pyx_v_boxes_dim, __pyx_t_14, __pyx_v_device_id); + + /* "nms/gpu_nms.pyx":32 + * sorted_dets = dets[order, :] + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + * keep = keep[:num_out] # <<<<<<<<<<<<<< + * return list(order[keep]) + */ + __pyx_t_5 = __Pyx_PyObject_GetSlice(((PyObject *)__pyx_v_keep), 0, __pyx_v_num_out, NULL, NULL, NULL, 0, 1, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 32, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 32, __pyx_L1_error) + __pyx_t_6 = ((PyArrayObject *)__pyx_t_5); + { + __Pyx_BufFmt_StackElem __pyx_stack[1]; + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_keep.rcbuffer->pybuffer); + __pyx_t_11 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_keep.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack); + if (unlikely(__pyx_t_11 < 0)) { + PyErr_Fetch(&__pyx_t_15, &__pyx_t_16, &__pyx_t_17); + if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_keep.rcbuffer->pybuffer, (PyObject*)__pyx_v_keep, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { + Py_XDECREF(__pyx_t_15); Py_XDECREF(__pyx_t_16); Py_XDECREF(__pyx_t_17); + __Pyx_RaiseBufferFallbackError(); + } else { + PyErr_Restore(__pyx_t_15, __pyx_t_16, __pyx_t_17); + } + } + __pyx_pybuffernd_keep.diminfo[0].strides = __pyx_pybuffernd_keep.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_keep.diminfo[0].shape = __pyx_pybuffernd_keep.rcbuffer->pybuffer.shape[0]; + if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 32, __pyx_L1_error) + } + __pyx_t_6 = 0; + __Pyx_DECREF_SET(__pyx_v_keep, ((PyArrayObject *)__pyx_t_5)); + __pyx_t_5 = 0; + + /* "nms/gpu_nms.pyx":33 + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + * keep = keep[:num_out] + * return list(order[keep]) # <<<<<<<<<<<<<< + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_5 = PyObject_GetItem(((PyObject *)__pyx_v_order), ((PyObject *)__pyx_v_keep)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 33, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_1 = PySequence_List(__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 33, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "nms/gpu_nms.pyx":16 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dets.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_keep.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_order.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_scores.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer); + __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} + __Pyx_AddTraceback("nms.gpu_nms.gpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + goto __pyx_L2; + __pyx_L0:; + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dets.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_keep.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_order.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_scores.rcbuffer->pybuffer); + __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_sorted_dets.rcbuffer->pybuffer); + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_keep); + __Pyx_XDECREF((PyObject *)__pyx_v_scores); + __Pyx_XDECREF((PyObject *)__pyx_v_order); + __Pyx_XDECREF((PyObject *)__pyx_v_sorted_dets); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":197 + * # experimental exception made for __getbuffer__ and __releasebuffer__ + * # -- the details of this may change. + * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< + * # This implementation of getbuffer is geared towards Cython + * # requirements, and does not yet fullfill the PEP. + */ + +/* Python wrapper */ +static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ +static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + int __pyx_r; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); + __pyx_r = __pyx_pf_5numpy_7ndarray___getbuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { + int __pyx_v_copy_shape; + int __pyx_v_i; + int __pyx_v_ndim; + int __pyx_v_endian_detector; + int __pyx_v_little_endian; + int __pyx_v_t; + char *__pyx_v_f; + PyArray_Descr *__pyx_v_descr = 0; + int __pyx_v_offset; + int __pyx_v_hasfields; + int __pyx_r; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + int __pyx_t_4; + int __pyx_t_5; + PyObject *__pyx_t_6 = NULL; + char *__pyx_t_7; + __Pyx_RefNannySetupContext("__getbuffer__", 0); + if (__pyx_v_info != NULL) { + __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(__pyx_v_info->obj); + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":203 + * # of flags + * + * if info == NULL: return # <<<<<<<<<<<<<< + * + * cdef int copy_shape, i, ndim + */ + __pyx_t_1 = ((__pyx_v_info == NULL) != 0); + if (__pyx_t_1) { + __pyx_r = 0; + goto __pyx_L0; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":206 + * + * cdef int copy_shape, i, ndim + * cdef int endian_detector = 1 # <<<<<<<<<<<<<< + * cdef bint little_endian = ((&endian_detector)[0] != 0) + * + */ + __pyx_v_endian_detector = 1; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":207 + * cdef int copy_shape, i, ndim + * cdef int endian_detector = 1 + * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< + * + * ndim = PyArray_NDIM(self) + */ + __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":209 + * cdef bint little_endian = ((&endian_detector)[0] != 0) + * + * ndim = PyArray_NDIM(self) # <<<<<<<<<<<<<< + * + * if sizeof(npy_intp) != sizeof(Py_ssize_t): + */ + __pyx_v_ndim = PyArray_NDIM(__pyx_v_self); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":211 + * ndim = PyArray_NDIM(self) + * + * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< + * copy_shape = 1 + * else: + */ + __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":212 + * + * if sizeof(npy_intp) != sizeof(Py_ssize_t): + * copy_shape = 1 # <<<<<<<<<<<<<< + * else: + * copy_shape = 0 + */ + __pyx_v_copy_shape = 1; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":211 + * ndim = PyArray_NDIM(self) + * + * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< + * copy_shape = 1 + * else: + */ + goto __pyx_L4; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":214 + * copy_shape = 1 + * else: + * copy_shape = 0 # <<<<<<<<<<<<<< + * + * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) + */ + /*else*/ { + __pyx_v_copy_shape = 0; + } + __pyx_L4:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":216 + * copy_shape = 0 + * + * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< + * and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)): + * raise ValueError(u"ndarray is not C contiguous") + */ + __pyx_t_2 = (((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) != 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L6_bool_binop_done; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":217 + * + * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) + * and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)): # <<<<<<<<<<<<<< + * raise ValueError(u"ndarray is not C contiguous") + * + */ + __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS) != 0)) != 0); + __pyx_t_1 = __pyx_t_2; + __pyx_L6_bool_binop_done:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":216 + * copy_shape = 0 + * + * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< + * and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)): + * raise ValueError(u"ndarray is not C contiguous") + */ + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":218 + * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) + * and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)): + * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< + * + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) + */ + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 218, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __PYX_ERR(1, 218, __pyx_L1_error) + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":216 + * copy_shape = 0 + * + * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) # <<<<<<<<<<<<<< + * and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)): + * raise ValueError(u"ndarray is not C contiguous") + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":220 + * raise ValueError(u"ndarray is not C contiguous") + * + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< + * and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)): + * raise ValueError(u"ndarray is not Fortran contiguous") + */ + __pyx_t_2 = (((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) != 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L9_bool_binop_done; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":221 + * + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) + * and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)): # <<<<<<<<<<<<<< + * raise ValueError(u"ndarray is not Fortran contiguous") + * + */ + __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS) != 0)) != 0); + __pyx_t_1 = __pyx_t_2; + __pyx_L9_bool_binop_done:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":220 + * raise ValueError(u"ndarray is not C contiguous") + * + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< + * and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)): + * raise ValueError(u"ndarray is not Fortran contiguous") + */ + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":222 + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) + * and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)): + * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< + * + * info.buf = PyArray_DATA(self) + */ + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __PYX_ERR(1, 222, __pyx_L1_error) + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":220 + * raise ValueError(u"ndarray is not C contiguous") + * + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) # <<<<<<<<<<<<<< + * and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)): + * raise ValueError(u"ndarray is not Fortran contiguous") + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":224 + * raise ValueError(u"ndarray is not Fortran contiguous") + * + * info.buf = PyArray_DATA(self) # <<<<<<<<<<<<<< + * info.ndim = ndim + * if copy_shape: + */ + __pyx_v_info->buf = PyArray_DATA(__pyx_v_self); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":225 + * + * info.buf = PyArray_DATA(self) + * info.ndim = ndim # <<<<<<<<<<<<<< + * if copy_shape: + * # Allocate new buffer for strides and shape info. + */ + __pyx_v_info->ndim = __pyx_v_ndim; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":226 + * info.buf = PyArray_DATA(self) + * info.ndim = ndim + * if copy_shape: # <<<<<<<<<<<<<< + * # Allocate new buffer for strides and shape info. + * # This is allocated as one block, strides first. + */ + __pyx_t_1 = (__pyx_v_copy_shape != 0); + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":229 + * # Allocate new buffer for strides and shape info. + * # This is allocated as one block, strides first. + * info.strides = stdlib.malloc(sizeof(Py_ssize_t) * ndim * 2) # <<<<<<<<<<<<<< + * info.shape = info.strides + ndim + * for i in range(ndim): + */ + __pyx_v_info->strides = ((Py_ssize_t *)malloc((((sizeof(Py_ssize_t)) * ((size_t)__pyx_v_ndim)) * 2))); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":230 + * # This is allocated as one block, strides first. + * info.strides = stdlib.malloc(sizeof(Py_ssize_t) * ndim * 2) + * info.shape = info.strides + ndim # <<<<<<<<<<<<<< + * for i in range(ndim): + * info.strides[i] = PyArray_STRIDES(self)[i] + */ + __pyx_v_info->shape = (__pyx_v_info->strides + __pyx_v_ndim); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":231 + * info.strides = stdlib.malloc(sizeof(Py_ssize_t) * ndim * 2) + * info.shape = info.strides + ndim + * for i in range(ndim): # <<<<<<<<<<<<<< + * info.strides[i] = PyArray_STRIDES(self)[i] + * info.shape[i] = PyArray_DIMS(self)[i] + */ + __pyx_t_4 = __pyx_v_ndim; + for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { + __pyx_v_i = __pyx_t_5; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":232 + * info.shape = info.strides + ndim + * for i in range(ndim): + * info.strides[i] = PyArray_STRIDES(self)[i] # <<<<<<<<<<<<<< + * info.shape[i] = PyArray_DIMS(self)[i] + * else: + */ + (__pyx_v_info->strides[__pyx_v_i]) = (PyArray_STRIDES(__pyx_v_self)[__pyx_v_i]); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":233 + * for i in range(ndim): + * info.strides[i] = PyArray_STRIDES(self)[i] + * info.shape[i] = PyArray_DIMS(self)[i] # <<<<<<<<<<<<<< + * else: + * info.strides = PyArray_STRIDES(self) + */ + (__pyx_v_info->shape[__pyx_v_i]) = (PyArray_DIMS(__pyx_v_self)[__pyx_v_i]); + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":226 + * info.buf = PyArray_DATA(self) + * info.ndim = ndim + * if copy_shape: # <<<<<<<<<<<<<< + * # Allocate new buffer for strides and shape info. + * # This is allocated as one block, strides first. + */ + goto __pyx_L11; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":235 + * info.shape[i] = PyArray_DIMS(self)[i] + * else: + * info.strides = PyArray_STRIDES(self) # <<<<<<<<<<<<<< + * info.shape = PyArray_DIMS(self) + * info.suboffsets = NULL + */ + /*else*/ { + __pyx_v_info->strides = ((Py_ssize_t *)PyArray_STRIDES(__pyx_v_self)); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":236 + * else: + * info.strides = PyArray_STRIDES(self) + * info.shape = PyArray_DIMS(self) # <<<<<<<<<<<<<< + * info.suboffsets = NULL + * info.itemsize = PyArray_ITEMSIZE(self) + */ + __pyx_v_info->shape = ((Py_ssize_t *)PyArray_DIMS(__pyx_v_self)); + } + __pyx_L11:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":237 + * info.strides = PyArray_STRIDES(self) + * info.shape = PyArray_DIMS(self) + * info.suboffsets = NULL # <<<<<<<<<<<<<< + * info.itemsize = PyArray_ITEMSIZE(self) + * info.readonly = not PyArray_ISWRITEABLE(self) + */ + __pyx_v_info->suboffsets = NULL; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":238 + * info.shape = PyArray_DIMS(self) + * info.suboffsets = NULL + * info.itemsize = PyArray_ITEMSIZE(self) # <<<<<<<<<<<<<< + * info.readonly = not PyArray_ISWRITEABLE(self) + * + */ + __pyx_v_info->itemsize = PyArray_ITEMSIZE(__pyx_v_self); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":239 + * info.suboffsets = NULL + * info.itemsize = PyArray_ITEMSIZE(self) + * info.readonly = not PyArray_ISWRITEABLE(self) # <<<<<<<<<<<<<< + * + * cdef int t + */ + __pyx_v_info->readonly = (!(PyArray_ISWRITEABLE(__pyx_v_self) != 0)); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":242 + * + * cdef int t + * cdef char* f = NULL # <<<<<<<<<<<<<< + * cdef dtype descr = self.descr + * cdef int offset + */ + __pyx_v_f = NULL; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":243 + * cdef int t + * cdef char* f = NULL + * cdef dtype descr = self.descr # <<<<<<<<<<<<<< + * cdef int offset + * + */ + __pyx_t_3 = ((PyObject *)__pyx_v_self->descr); + __Pyx_INCREF(__pyx_t_3); + __pyx_v_descr = ((PyArray_Descr *)__pyx_t_3); + __pyx_t_3 = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":246 + * cdef int offset + * + * cdef bint hasfields = PyDataType_HASFIELDS(descr) # <<<<<<<<<<<<<< + * + * if not hasfields and not copy_shape: + */ + __pyx_v_hasfields = PyDataType_HASFIELDS(__pyx_v_descr); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":248 + * cdef bint hasfields = PyDataType_HASFIELDS(descr) + * + * if not hasfields and not copy_shape: # <<<<<<<<<<<<<< + * # do not call releasebuffer + * info.obj = None + */ + __pyx_t_2 = ((!(__pyx_v_hasfields != 0)) != 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L15_bool_binop_done; + } + __pyx_t_2 = ((!(__pyx_v_copy_shape != 0)) != 0); + __pyx_t_1 = __pyx_t_2; + __pyx_L15_bool_binop_done:; + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":250 + * if not hasfields and not copy_shape: + * # do not call releasebuffer + * info.obj = None # <<<<<<<<<<<<<< + * else: + * # need to call releasebuffer + */ + __Pyx_INCREF(Py_None); + __Pyx_GIVEREF(Py_None); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = Py_None; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":248 + * cdef bint hasfields = PyDataType_HASFIELDS(descr) + * + * if not hasfields and not copy_shape: # <<<<<<<<<<<<<< + * # do not call releasebuffer + * info.obj = None + */ + goto __pyx_L14; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":253 + * else: + * # need to call releasebuffer + * info.obj = self # <<<<<<<<<<<<<< + * + * if not hasfields: + */ + /*else*/ { + __Pyx_INCREF(((PyObject *)__pyx_v_self)); + __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); + __pyx_v_info->obj = ((PyObject *)__pyx_v_self); + } + __pyx_L14:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":255 + * info.obj = self + * + * if not hasfields: # <<<<<<<<<<<<<< + * t = descr.type_num + * if ((descr.byteorder == c'>' and little_endian) or + */ + __pyx_t_1 = ((!(__pyx_v_hasfields != 0)) != 0); + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":256 + * + * if not hasfields: + * t = descr.type_num # <<<<<<<<<<<<<< + * if ((descr.byteorder == c'>' and little_endian) or + * (descr.byteorder == c'<' and not little_endian)): + */ + __pyx_t_4 = __pyx_v_descr->type_num; + __pyx_v_t = __pyx_t_4; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":257 + * if not hasfields: + * t = descr.type_num + * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< + * (descr.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") + */ + __pyx_t_2 = ((__pyx_v_descr->byteorder == '>') != 0); + if (!__pyx_t_2) { + goto __pyx_L20_next_or; + } else { + } + __pyx_t_2 = (__pyx_v_little_endian != 0); + if (!__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L19_bool_binop_done; + } + __pyx_L20_next_or:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":258 + * t = descr.type_num + * if ((descr.byteorder == c'>' and little_endian) or + * (descr.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< + * raise ValueError(u"Non-native byte order not supported") + * if t == NPY_BYTE: f = "b" + */ + __pyx_t_2 = ((__pyx_v_descr->byteorder == '<') != 0); + if (__pyx_t_2) { + } else { + __pyx_t_1 = __pyx_t_2; + goto __pyx_L19_bool_binop_done; + } + __pyx_t_2 = ((!(__pyx_v_little_endian != 0)) != 0); + __pyx_t_1 = __pyx_t_2; + __pyx_L19_bool_binop_done:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":257 + * if not hasfields: + * t = descr.type_num + * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< + * (descr.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") + */ + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":259 + * if ((descr.byteorder == c'>' and little_endian) or + * (descr.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< + * if t == NPY_BYTE: f = "b" + * elif t == NPY_UBYTE: f = "B" + */ + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 259, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __PYX_ERR(1, 259, __pyx_L1_error) + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":257 + * if not hasfields: + * t = descr.type_num + * if ((descr.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< + * (descr.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":260 + * (descr.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") + * if t == NPY_BYTE: f = "b" # <<<<<<<<<<<<<< + * elif t == NPY_UBYTE: f = "B" + * elif t == NPY_SHORT: f = "h" + */ + switch (__pyx_v_t) { + case NPY_BYTE: + __pyx_v_f = ((char *)"b"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":261 + * raise ValueError(u"Non-native byte order not supported") + * if t == NPY_BYTE: f = "b" + * elif t == NPY_UBYTE: f = "B" # <<<<<<<<<<<<<< + * elif t == NPY_SHORT: f = "h" + * elif t == NPY_USHORT: f = "H" + */ + case NPY_UBYTE: + __pyx_v_f = ((char *)"B"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":262 + * if t == NPY_BYTE: f = "b" + * elif t == NPY_UBYTE: f = "B" + * elif t == NPY_SHORT: f = "h" # <<<<<<<<<<<<<< + * elif t == NPY_USHORT: f = "H" + * elif t == NPY_INT: f = "i" + */ + case NPY_SHORT: + __pyx_v_f = ((char *)"h"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":263 + * elif t == NPY_UBYTE: f = "B" + * elif t == NPY_SHORT: f = "h" + * elif t == NPY_USHORT: f = "H" # <<<<<<<<<<<<<< + * elif t == NPY_INT: f = "i" + * elif t == NPY_UINT: f = "I" + */ + case NPY_USHORT: + __pyx_v_f = ((char *)"H"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":264 + * elif t == NPY_SHORT: f = "h" + * elif t == NPY_USHORT: f = "H" + * elif t == NPY_INT: f = "i" # <<<<<<<<<<<<<< + * elif t == NPY_UINT: f = "I" + * elif t == NPY_LONG: f = "l" + */ + case NPY_INT: + __pyx_v_f = ((char *)"i"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":265 + * elif t == NPY_USHORT: f = "H" + * elif t == NPY_INT: f = "i" + * elif t == NPY_UINT: f = "I" # <<<<<<<<<<<<<< + * elif t == NPY_LONG: f = "l" + * elif t == NPY_ULONG: f = "L" + */ + case NPY_UINT: + __pyx_v_f = ((char *)"I"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":266 + * elif t == NPY_INT: f = "i" + * elif t == NPY_UINT: f = "I" + * elif t == NPY_LONG: f = "l" # <<<<<<<<<<<<<< + * elif t == NPY_ULONG: f = "L" + * elif t == NPY_LONGLONG: f = "q" + */ + case NPY_LONG: + __pyx_v_f = ((char *)"l"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":267 + * elif t == NPY_UINT: f = "I" + * elif t == NPY_LONG: f = "l" + * elif t == NPY_ULONG: f = "L" # <<<<<<<<<<<<<< + * elif t == NPY_LONGLONG: f = "q" + * elif t == NPY_ULONGLONG: f = "Q" + */ + case NPY_ULONG: + __pyx_v_f = ((char *)"L"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":268 + * elif t == NPY_LONG: f = "l" + * elif t == NPY_ULONG: f = "L" + * elif t == NPY_LONGLONG: f = "q" # <<<<<<<<<<<<<< + * elif t == NPY_ULONGLONG: f = "Q" + * elif t == NPY_FLOAT: f = "f" + */ + case NPY_LONGLONG: + __pyx_v_f = ((char *)"q"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":269 + * elif t == NPY_ULONG: f = "L" + * elif t == NPY_LONGLONG: f = "q" + * elif t == NPY_ULONGLONG: f = "Q" # <<<<<<<<<<<<<< + * elif t == NPY_FLOAT: f = "f" + * elif t == NPY_DOUBLE: f = "d" + */ + case NPY_ULONGLONG: + __pyx_v_f = ((char *)"Q"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":270 + * elif t == NPY_LONGLONG: f = "q" + * elif t == NPY_ULONGLONG: f = "Q" + * elif t == NPY_FLOAT: f = "f" # <<<<<<<<<<<<<< + * elif t == NPY_DOUBLE: f = "d" + * elif t == NPY_LONGDOUBLE: f = "g" + */ + case NPY_FLOAT: + __pyx_v_f = ((char *)"f"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":271 + * elif t == NPY_ULONGLONG: f = "Q" + * elif t == NPY_FLOAT: f = "f" + * elif t == NPY_DOUBLE: f = "d" # <<<<<<<<<<<<<< + * elif t == NPY_LONGDOUBLE: f = "g" + * elif t == NPY_CFLOAT: f = "Zf" + */ + case NPY_DOUBLE: + __pyx_v_f = ((char *)"d"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":272 + * elif t == NPY_FLOAT: f = "f" + * elif t == NPY_DOUBLE: f = "d" + * elif t == NPY_LONGDOUBLE: f = "g" # <<<<<<<<<<<<<< + * elif t == NPY_CFLOAT: f = "Zf" + * elif t == NPY_CDOUBLE: f = "Zd" + */ + case NPY_LONGDOUBLE: + __pyx_v_f = ((char *)"g"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":273 + * elif t == NPY_DOUBLE: f = "d" + * elif t == NPY_LONGDOUBLE: f = "g" + * elif t == NPY_CFLOAT: f = "Zf" # <<<<<<<<<<<<<< + * elif t == NPY_CDOUBLE: f = "Zd" + * elif t == NPY_CLONGDOUBLE: f = "Zg" + */ + case NPY_CFLOAT: + __pyx_v_f = ((char *)"Zf"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":274 + * elif t == NPY_LONGDOUBLE: f = "g" + * elif t == NPY_CFLOAT: f = "Zf" + * elif t == NPY_CDOUBLE: f = "Zd" # <<<<<<<<<<<<<< + * elif t == NPY_CLONGDOUBLE: f = "Zg" + * elif t == NPY_OBJECT: f = "O" + */ + case NPY_CDOUBLE: + __pyx_v_f = ((char *)"Zd"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":275 + * elif t == NPY_CFLOAT: f = "Zf" + * elif t == NPY_CDOUBLE: f = "Zd" + * elif t == NPY_CLONGDOUBLE: f = "Zg" # <<<<<<<<<<<<<< + * elif t == NPY_OBJECT: f = "O" + * else: + */ + case NPY_CLONGDOUBLE: + __pyx_v_f = ((char *)"Zg"); + break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":276 + * elif t == NPY_CDOUBLE: f = "Zd" + * elif t == NPY_CLONGDOUBLE: f = "Zg" + * elif t == NPY_OBJECT: f = "O" # <<<<<<<<<<<<<< + * else: + * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) + */ + case NPY_OBJECT: + __pyx_v_f = ((char *)"O"); + break; + default: + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":278 + * elif t == NPY_OBJECT: f = "O" + * else: + * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< + * info.format = f + * return + */ + __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 278, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_6 = PyUnicode_Format(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 278, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 278, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_6); + __pyx_t_6 = 0; + __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_t_3, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 278, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_Raise(__pyx_t_6, 0, 0, 0); + __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __PYX_ERR(1, 278, __pyx_L1_error) + break; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":279 + * else: + * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) + * info.format = f # <<<<<<<<<<<<<< + * return + * else: + */ + __pyx_v_info->format = __pyx_v_f; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":280 + * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) + * info.format = f + * return # <<<<<<<<<<<<<< + * else: + * info.format = stdlib.malloc(_buffer_format_string_len) + */ + __pyx_r = 0; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":255 + * info.obj = self + * + * if not hasfields: # <<<<<<<<<<<<<< + * t = descr.type_num + * if ((descr.byteorder == c'>' and little_endian) or + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":282 + * return + * else: + * info.format = stdlib.malloc(_buffer_format_string_len) # <<<<<<<<<<<<<< + * info.format[0] = c'^' # Native data types, manual alignment + * offset = 0 + */ + /*else*/ { + __pyx_v_info->format = ((char *)malloc(0xFF)); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":283 + * else: + * info.format = stdlib.malloc(_buffer_format_string_len) + * info.format[0] = c'^' # Native data types, manual alignment # <<<<<<<<<<<<<< + * offset = 0 + * f = _util_dtypestring(descr, info.format + 1, + */ + (__pyx_v_info->format[0]) = '^'; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":284 + * info.format = stdlib.malloc(_buffer_format_string_len) + * info.format[0] = c'^' # Native data types, manual alignment + * offset = 0 # <<<<<<<<<<<<<< + * f = _util_dtypestring(descr, info.format + 1, + * info.format + _buffer_format_string_len, + */ + __pyx_v_offset = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":285 + * info.format[0] = c'^' # Native data types, manual alignment + * offset = 0 + * f = _util_dtypestring(descr, info.format + 1, # <<<<<<<<<<<<<< + * info.format + _buffer_format_string_len, + * &offset) + */ + __pyx_t_7 = __pyx_f_5numpy__util_dtypestring(__pyx_v_descr, (__pyx_v_info->format + 1), (__pyx_v_info->format + 0xFF), (&__pyx_v_offset)); if (unlikely(__pyx_t_7 == NULL)) __PYX_ERR(1, 285, __pyx_L1_error) + __pyx_v_f = __pyx_t_7; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":288 + * info.format + _buffer_format_string_len, + * &offset) + * f[0] = c'\0' # Terminate format string # <<<<<<<<<<<<<< + * + * def __releasebuffer__(ndarray self, Py_buffer* info): + */ + (__pyx_v_f[0]) = '\x00'; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":197 + * # experimental exception made for __getbuffer__ and __releasebuffer__ + * # -- the details of this may change. + * def __getbuffer__(ndarray self, Py_buffer* info, int flags): # <<<<<<<<<<<<<< + * # This implementation of getbuffer is geared towards Cython + * # requirements, and does not yet fullfill the PEP. + */ + + /* function exit code */ + __pyx_r = 0; + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("numpy.ndarray.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = -1; + if (__pyx_v_info != NULL && __pyx_v_info->obj != NULL) { + __Pyx_GOTREF(__pyx_v_info->obj); + __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = NULL; + } + goto __pyx_L2; + __pyx_L0:; + if (__pyx_v_info != NULL && __pyx_v_info->obj == Py_None) { + __Pyx_GOTREF(Py_None); + __Pyx_DECREF(Py_None); __pyx_v_info->obj = NULL; + } + __pyx_L2:; + __Pyx_XDECREF((PyObject *)__pyx_v_descr); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":290 + * f[0] = c'\0' # Terminate format string + * + * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< + * if PyArray_HASFIELDS(self): + * stdlib.free(info.format) + */ + +/* Python wrapper */ +static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/ +static CYTHON_UNUSED void __pyx_pw_5numpy_7ndarray_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0); + __pyx_pf_5numpy_7ndarray_2__releasebuffer__(((PyArrayObject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info)); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info) { + __Pyx_RefNannyDeclarations + int __pyx_t_1; + __Pyx_RefNannySetupContext("__releasebuffer__", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":291 + * + * def __releasebuffer__(ndarray self, Py_buffer* info): + * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< + * stdlib.free(info.format) + * if sizeof(npy_intp) != sizeof(Py_ssize_t): + */ + __pyx_t_1 = (PyArray_HASFIELDS(__pyx_v_self) != 0); + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":292 + * def __releasebuffer__(ndarray self, Py_buffer* info): + * if PyArray_HASFIELDS(self): + * stdlib.free(info.format) # <<<<<<<<<<<<<< + * if sizeof(npy_intp) != sizeof(Py_ssize_t): + * stdlib.free(info.strides) + */ + free(__pyx_v_info->format); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":291 + * + * def __releasebuffer__(ndarray self, Py_buffer* info): + * if PyArray_HASFIELDS(self): # <<<<<<<<<<<<<< + * stdlib.free(info.format) + * if sizeof(npy_intp) != sizeof(Py_ssize_t): + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":293 + * if PyArray_HASFIELDS(self): + * stdlib.free(info.format) + * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< + * stdlib.free(info.strides) + * # info.shape was stored after info.strides in the same block + */ + __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0); + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":294 + * stdlib.free(info.format) + * if sizeof(npy_intp) != sizeof(Py_ssize_t): + * stdlib.free(info.strides) # <<<<<<<<<<<<<< + * # info.shape was stored after info.strides in the same block + * + */ + free(__pyx_v_info->strides); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":293 + * if PyArray_HASFIELDS(self): + * stdlib.free(info.format) + * if sizeof(npy_intp) != sizeof(Py_ssize_t): # <<<<<<<<<<<<<< + * stdlib.free(info.strides) + * # info.shape was stored after info.strides in the same block + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":290 + * f[0] = c'\0' # Terminate format string + * + * def __releasebuffer__(ndarray self, Py_buffer* info): # <<<<<<<<<<<<<< + * if PyArray_HASFIELDS(self): + * stdlib.free(info.format) + */ + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":770 + * ctypedef npy_cdouble complex_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":771 + * + * cdef inline object PyArray_MultiIterNew1(a): + * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew2(a, b): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 771, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":770 + * ctypedef npy_cdouble complex_t + * + * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(1, a) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":773 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":774 + * + * cdef inline object PyArray_MultiIterNew2(a, b): + * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 774, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":773 + * return PyArray_MultiIterNew(1, a) + * + * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(2, a, b) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":776 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":777 + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): + * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 777, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":776 + * return PyArray_MultiIterNew(2, a, b) + * + * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(3, a, b, c) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":779 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":780 + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): + * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 780, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":779 + * return PyArray_MultiIterNew(3, a, b, c) + * + * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(4, a, b, c, d) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":782 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":783 + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): + * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< + * + * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: + */ + __Pyx_XDECREF(__pyx_r); + __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 783, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_r = __pyx_t_1; + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":782 + * return PyArray_MultiIterNew(4, a, b, c, d) + * + * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":785 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< + * # Recursive utility function used in __getbuffer__ to get format + * # string. The new location in the format string is returned. + */ + +static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx_v_descr, char *__pyx_v_f, char *__pyx_v_end, int *__pyx_v_offset) { + PyArray_Descr *__pyx_v_child = 0; + int __pyx_v_endian_detector; + int __pyx_v_little_endian; + PyObject *__pyx_v_fields = 0; + PyObject *__pyx_v_childname = NULL; + PyObject *__pyx_v_new_offset = NULL; + PyObject *__pyx_v_t = NULL; + char *__pyx_r; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + Py_ssize_t __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + int __pyx_t_5; + int __pyx_t_6; + int __pyx_t_7; + long __pyx_t_8; + char *__pyx_t_9; + __Pyx_RefNannySetupContext("_util_dtypestring", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":790 + * + * cdef dtype child + * cdef int endian_detector = 1 # <<<<<<<<<<<<<< + * cdef bint little_endian = ((&endian_detector)[0] != 0) + * cdef tuple fields + */ + __pyx_v_endian_detector = 1; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":791 + * cdef dtype child + * cdef int endian_detector = 1 + * cdef bint little_endian = ((&endian_detector)[0] != 0) # <<<<<<<<<<<<<< + * cdef tuple fields + * + */ + __pyx_v_little_endian = ((((char *)(&__pyx_v_endian_detector))[0]) != 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":794 + * cdef tuple fields + * + * for childname in descr.names: # <<<<<<<<<<<<<< + * fields = descr.fields[childname] + * child, new_offset = fields + */ + if (unlikely(__pyx_v_descr->names == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(1, 794, __pyx_L1_error) + } + __pyx_t_1 = __pyx_v_descr->names; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0; + for (;;) { + if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break; + #if CYTHON_COMPILING_IN_CPYTHON + __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(1, 794, __pyx_L1_error) + #else + __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 794, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + __Pyx_XDECREF_SET(__pyx_v_childname, __pyx_t_3); + __pyx_t_3 = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":795 + * + * for childname in descr.names: + * fields = descr.fields[childname] # <<<<<<<<<<<<<< + * child, new_offset = fields + * + */ + if (unlikely(__pyx_v_descr->fields == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(1, 795, __pyx_L1_error) + } + __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v_descr->fields, __pyx_v_childname); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 795, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(1, 795, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_fields, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":796 + * for childname in descr.names: + * fields = descr.fields[childname] + * child, new_offset = fields # <<<<<<<<<<<<<< + * + * if (end - f) - (new_offset - offset[0]) < 15: + */ + if (likely(__pyx_v_fields != Py_None)) { + PyObject* sequence = __pyx_v_fields; + #if CYTHON_COMPILING_IN_CPYTHON + Py_ssize_t size = Py_SIZE(sequence); + #else + Py_ssize_t size = PySequence_Size(sequence); + #endif + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(1, 796, __pyx_L1_error) + } + #if CYTHON_COMPILING_IN_CPYTHON + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 796, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 796, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(1, 796, __pyx_L1_error) + } + if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_dtype))))) __PYX_ERR(1, 796, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_child, ((PyArray_Descr *)__pyx_t_3)); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_offset, __pyx_t_4); + __pyx_t_4 = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":798 + * child, new_offset = fields + * + * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< + * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") + * + */ + __pyx_t_4 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 798, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyNumber_Subtract(__pyx_v_new_offset, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 798, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 798, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = ((((__pyx_v_end - __pyx_v_f) - ((int)__pyx_t_5)) < 15) != 0); + if (__pyx_t_6) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":799 + * + * if (end - f) - (new_offset - offset[0]) < 15: + * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< + * + * if ((child.byteorder == c'>' and little_endian) or + */ + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 799, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __PYX_ERR(1, 799, __pyx_L1_error) + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":798 + * child, new_offset = fields + * + * if (end - f) - (new_offset - offset[0]) < 15: # <<<<<<<<<<<<<< + * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") + * + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":801 + * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") + * + * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< + * (child.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") + */ + __pyx_t_7 = ((__pyx_v_child->byteorder == '>') != 0); + if (!__pyx_t_7) { + goto __pyx_L8_next_or; + } else { + } + __pyx_t_7 = (__pyx_v_little_endian != 0); + if (!__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L7_bool_binop_done; + } + __pyx_L8_next_or:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":802 + * + * if ((child.byteorder == c'>' and little_endian) or + * (child.byteorder == c'<' and not little_endian)): # <<<<<<<<<<<<<< + * raise ValueError(u"Non-native byte order not supported") + * # One could encode it in the format string and have Cython + */ + __pyx_t_7 = ((__pyx_v_child->byteorder == '<') != 0); + if (__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L7_bool_binop_done; + } + __pyx_t_7 = ((!(__pyx_v_little_endian != 0)) != 0); + __pyx_t_6 = __pyx_t_7; + __pyx_L7_bool_binop_done:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":801 + * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") + * + * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< + * (child.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") + */ + if (__pyx_t_6) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":803 + * if ((child.byteorder == c'>' and little_endian) or + * (child.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< + * # One could encode it in the format string and have Cython + * # complain instead, BUT: < and > in format strings also imply + */ + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 803, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __PYX_ERR(1, 803, __pyx_L1_error) + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":801 + * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") + * + * if ((child.byteorder == c'>' and little_endian) or # <<<<<<<<<<<<<< + * (child.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":813 + * + * # Output padding bytes + * while offset[0] < new_offset: # <<<<<<<<<<<<<< + * f[0] = 120 # "x"; pad byte + * f += 1 + */ + while (1) { + __pyx_t_3 = __Pyx_PyInt_From_int((__pyx_v_offset[0])); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 813, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_v_new_offset, Py_LT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 813, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 813, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (!__pyx_t_6) break; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":814 + * # Output padding bytes + * while offset[0] < new_offset: + * f[0] = 120 # "x"; pad byte # <<<<<<<<<<<<<< + * f += 1 + * offset[0] += 1 + */ + (__pyx_v_f[0]) = 0x78; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":815 + * while offset[0] < new_offset: + * f[0] = 120 # "x"; pad byte + * f += 1 # <<<<<<<<<<<<<< + * offset[0] += 1 + * + */ + __pyx_v_f = (__pyx_v_f + 1); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":816 + * f[0] = 120 # "x"; pad byte + * f += 1 + * offset[0] += 1 # <<<<<<<<<<<<<< + * + * offset[0] += child.itemsize + */ + __pyx_t_8 = 0; + (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + 1); + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":818 + * offset[0] += 1 + * + * offset[0] += child.itemsize # <<<<<<<<<<<<<< + * + * if not PyDataType_HASFIELDS(child): + */ + __pyx_t_8 = 0; + (__pyx_v_offset[__pyx_t_8]) = ((__pyx_v_offset[__pyx_t_8]) + __pyx_v_child->elsize); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":820 + * offset[0] += child.itemsize + * + * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< + * t = child.type_num + * if end - f < 5: + */ + __pyx_t_6 = ((!(PyDataType_HASFIELDS(__pyx_v_child) != 0)) != 0); + if (__pyx_t_6) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":821 + * + * if not PyDataType_HASFIELDS(child): + * t = child.type_num # <<<<<<<<<<<<<< + * if end - f < 5: + * raise RuntimeError(u"Format string allocated too short.") + */ + __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_child->type_num); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 821, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4); + __pyx_t_4 = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":822 + * if not PyDataType_HASFIELDS(child): + * t = child.type_num + * if end - f < 5: # <<<<<<<<<<<<<< + * raise RuntimeError(u"Format string allocated too short.") + * + */ + __pyx_t_6 = (((__pyx_v_end - __pyx_v_f) < 5) != 0); + if (__pyx_t_6) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":823 + * t = child.type_num + * if end - f < 5: + * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< + * + * # Until ticket #99 is fixed, use integers to avoid warnings + */ + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple__10, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 823, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_Raise(__pyx_t_4, 0, 0, 0); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __PYX_ERR(1, 823, __pyx_L1_error) + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":822 + * if not PyDataType_HASFIELDS(child): + * t = child.type_num + * if end - f < 5: # <<<<<<<<<<<<<< + * raise RuntimeError(u"Format string allocated too short.") + * + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":826 + * + * # Until ticket #99 is fixed, use integers to avoid warnings + * if t == NPY_BYTE: f[0] = 98 #"b" # <<<<<<<<<<<<<< + * elif t == NPY_UBYTE: f[0] = 66 #"B" + * elif t == NPY_SHORT: f[0] = 104 #"h" + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_BYTE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 826, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 826, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 826, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 98; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":827 + * # Until ticket #99 is fixed, use integers to avoid warnings + * if t == NPY_BYTE: f[0] = 98 #"b" + * elif t == NPY_UBYTE: f[0] = 66 #"B" # <<<<<<<<<<<<<< + * elif t == NPY_SHORT: f[0] = 104 #"h" + * elif t == NPY_USHORT: f[0] = 72 #"H" + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UBYTE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 827, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 827, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 827, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 66; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":828 + * if t == NPY_BYTE: f[0] = 98 #"b" + * elif t == NPY_UBYTE: f[0] = 66 #"B" + * elif t == NPY_SHORT: f[0] = 104 #"h" # <<<<<<<<<<<<<< + * elif t == NPY_USHORT: f[0] = 72 #"H" + * elif t == NPY_INT: f[0] = 105 #"i" + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_SHORT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 828, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 828, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 828, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 0x68; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":829 + * elif t == NPY_UBYTE: f[0] = 66 #"B" + * elif t == NPY_SHORT: f[0] = 104 #"h" + * elif t == NPY_USHORT: f[0] = 72 #"H" # <<<<<<<<<<<<<< + * elif t == NPY_INT: f[0] = 105 #"i" + * elif t == NPY_UINT: f[0] = 73 #"I" + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_USHORT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 829, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 829, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 829, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 72; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":830 + * elif t == NPY_SHORT: f[0] = 104 #"h" + * elif t == NPY_USHORT: f[0] = 72 #"H" + * elif t == NPY_INT: f[0] = 105 #"i" # <<<<<<<<<<<<<< + * elif t == NPY_UINT: f[0] = 73 #"I" + * elif t == NPY_LONG: f[0] = 108 #"l" + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_INT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 830, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 830, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 830, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 0x69; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":831 + * elif t == NPY_USHORT: f[0] = 72 #"H" + * elif t == NPY_INT: f[0] = 105 #"i" + * elif t == NPY_UINT: f[0] = 73 #"I" # <<<<<<<<<<<<<< + * elif t == NPY_LONG: f[0] = 108 #"l" + * elif t == NPY_ULONG: f[0] = 76 #"L" + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_UINT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 831, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 831, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 831, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 73; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":832 + * elif t == NPY_INT: f[0] = 105 #"i" + * elif t == NPY_UINT: f[0] = 73 #"I" + * elif t == NPY_LONG: f[0] = 108 #"l" # <<<<<<<<<<<<<< + * elif t == NPY_ULONG: f[0] = 76 #"L" + * elif t == NPY_LONGLONG: f[0] = 113 #"q" + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 832, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 832, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 832, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 0x6C; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":833 + * elif t == NPY_UINT: f[0] = 73 #"I" + * elif t == NPY_LONG: f[0] = 108 #"l" + * elif t == NPY_ULONG: f[0] = 76 #"L" # <<<<<<<<<<<<<< + * elif t == NPY_LONGLONG: f[0] = 113 #"q" + * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 833, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 833, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 833, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 76; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":834 + * elif t == NPY_LONG: f[0] = 108 #"l" + * elif t == NPY_ULONG: f[0] = 76 #"L" + * elif t == NPY_LONGLONG: f[0] = 113 #"q" # <<<<<<<<<<<<<< + * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" + * elif t == NPY_FLOAT: f[0] = 102 #"f" + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGLONG); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 834, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 834, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 834, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 0x71; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":835 + * elif t == NPY_ULONG: f[0] = 76 #"L" + * elif t == NPY_LONGLONG: f[0] = 113 #"q" + * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" # <<<<<<<<<<<<<< + * elif t == NPY_FLOAT: f[0] = 102 #"f" + * elif t == NPY_DOUBLE: f[0] = 100 #"d" + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_ULONGLONG); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 835, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 835, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 835, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 81; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":836 + * elif t == NPY_LONGLONG: f[0] = 113 #"q" + * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" + * elif t == NPY_FLOAT: f[0] = 102 #"f" # <<<<<<<<<<<<<< + * elif t == NPY_DOUBLE: f[0] = 100 #"d" + * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_FLOAT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 836, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 836, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 836, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 0x66; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":837 + * elif t == NPY_ULONGLONG: f[0] = 81 #"Q" + * elif t == NPY_FLOAT: f[0] = 102 #"f" + * elif t == NPY_DOUBLE: f[0] = 100 #"d" # <<<<<<<<<<<<<< + * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" + * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 837, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 837, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 837, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 0x64; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":838 + * elif t == NPY_FLOAT: f[0] = 102 #"f" + * elif t == NPY_DOUBLE: f[0] = 100 #"d" + * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" # <<<<<<<<<<<<<< + * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf + * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_LONGDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 838, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 838, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 838, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 0x67; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":839 + * elif t == NPY_DOUBLE: f[0] = 100 #"d" + * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" + * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf # <<<<<<<<<<<<<< + * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd + * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CFLOAT); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 839, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 839, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 839, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 0x66; + __pyx_v_f = (__pyx_v_f + 1); + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":840 + * elif t == NPY_LONGDOUBLE: f[0] = 103 #"g" + * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf + * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd # <<<<<<<<<<<<<< + * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg + * elif t == NPY_OBJECT: f[0] = 79 #"O" + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CDOUBLE); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 840, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 840, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 840, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 0x64; + __pyx_v_f = (__pyx_v_f + 1); + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":841 + * elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1 # Zf + * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd + * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg # <<<<<<<<<<<<<< + * elif t == NPY_OBJECT: f[0] = 79 #"O" + * else: + */ + __pyx_t_3 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_CLONGDOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 841, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyObject_RichCompare(__pyx_v_t, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 841, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 841, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 90; + (__pyx_v_f[1]) = 0x67; + __pyx_v_f = (__pyx_v_f + 1); + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":842 + * elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1 # Zd + * elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1 # Zg + * elif t == NPY_OBJECT: f[0] = 79 #"O" # <<<<<<<<<<<<<< + * else: + * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) + */ + __pyx_t_4 = __Pyx_PyInt_From_enum__NPY_TYPES(NPY_OBJECT); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 842, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyObject_RichCompare(__pyx_v_t, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 842, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(1, 842, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (__pyx_t_6) { + (__pyx_v_f[0]) = 79; + goto __pyx_L15; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":844 + * elif t == NPY_OBJECT: f[0] = 79 #"O" + * else: + * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) # <<<<<<<<<<<<<< + * f += 1 + * else: + */ + /*else*/ { + __pyx_t_3 = PyUnicode_Format(__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_v_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 844, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 844, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_3); + __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 844, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_Raise(__pyx_t_3, 0, 0, 0); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __PYX_ERR(1, 844, __pyx_L1_error) + } + __pyx_L15:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":845 + * else: + * raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t) + * f += 1 # <<<<<<<<<<<<<< + * else: + * # Cython ignores struct boundary information ("T{...}"), + */ + __pyx_v_f = (__pyx_v_f + 1); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":820 + * offset[0] += child.itemsize + * + * if not PyDataType_HASFIELDS(child): # <<<<<<<<<<<<<< + * t = child.type_num + * if end - f < 5: + */ + goto __pyx_L13; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":849 + * # Cython ignores struct boundary information ("T{...}"), + * # so don't output it + * f = _util_dtypestring(child, f, end, offset) # <<<<<<<<<<<<<< + * return f + * + */ + /*else*/ { + __pyx_t_9 = __pyx_f_5numpy__util_dtypestring(__pyx_v_child, __pyx_v_f, __pyx_v_end, __pyx_v_offset); if (unlikely(__pyx_t_9 == NULL)) __PYX_ERR(1, 849, __pyx_L1_error) + __pyx_v_f = __pyx_t_9; + } + __pyx_L13:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":794 + * cdef tuple fields + * + * for childname in descr.names: # <<<<<<<<<<<<<< + * fields = descr.fields[childname] + * child, new_offset = fields + */ + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":850 + * # so don't output it + * f = _util_dtypestring(child, f, end, offset) + * return f # <<<<<<<<<<<<<< + * + * + */ + __pyx_r = __pyx_v_f; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":785 + * return PyArray_MultiIterNew(5, a, b, c, d, e) + * + * cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset) except NULL: # <<<<<<<<<<<<<< + * # Recursive utility function used in __getbuffer__ to get format + * # string. The new location in the format string is returned. + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("numpy._util_dtypestring", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF((PyObject *)__pyx_v_child); + __Pyx_XDECREF(__pyx_v_fields); + __Pyx_XDECREF(__pyx_v_childname); + __Pyx_XDECREF(__pyx_v_new_offset); + __Pyx_XDECREF(__pyx_v_t); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":966 + * + * + * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< + * cdef PyObject* baseptr + * if base is None: + */ + +static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { + PyObject *__pyx_v_baseptr; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + __Pyx_RefNannySetupContext("set_array_base", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":968 + * cdef inline void set_array_base(ndarray arr, object base): + * cdef PyObject* baseptr + * if base is None: # <<<<<<<<<<<<<< + * baseptr = NULL + * else: + */ + __pyx_t_1 = (__pyx_v_base == Py_None); + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":969 + * cdef PyObject* baseptr + * if base is None: + * baseptr = NULL # <<<<<<<<<<<<<< + * else: + * Py_INCREF(base) # important to do this before decref below! + */ + __pyx_v_baseptr = NULL; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":968 + * cdef inline void set_array_base(ndarray arr, object base): + * cdef PyObject* baseptr + * if base is None: # <<<<<<<<<<<<<< + * baseptr = NULL + * else: + */ + goto __pyx_L3; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":971 + * baseptr = NULL + * else: + * Py_INCREF(base) # important to do this before decref below! # <<<<<<<<<<<<<< + * baseptr = base + * Py_XDECREF(arr.base) + */ + /*else*/ { + Py_INCREF(__pyx_v_base); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":972 + * else: + * Py_INCREF(base) # important to do this before decref below! + * baseptr = base # <<<<<<<<<<<<<< + * Py_XDECREF(arr.base) + * arr.base = baseptr + */ + __pyx_v_baseptr = ((PyObject *)__pyx_v_base); + } + __pyx_L3:; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":973 + * Py_INCREF(base) # important to do this before decref below! + * baseptr = base + * Py_XDECREF(arr.base) # <<<<<<<<<<<<<< + * arr.base = baseptr + * + */ + Py_XDECREF(__pyx_v_arr->base); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":974 + * baseptr = base + * Py_XDECREF(arr.base) + * arr.base = baseptr # <<<<<<<<<<<<<< + * + * cdef inline object get_array_base(ndarray arr): + */ + __pyx_v_arr->base = __pyx_v_baseptr; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":966 + * + * + * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< + * cdef PyObject* baseptr + * if base is None: + */ + + /* function exit code */ + __Pyx_RefNannyFinishContext(); +} + +/* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":976 + * arr.base = baseptr + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * if arr.base is NULL: + * return None + */ + +static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + __Pyx_RefNannySetupContext("get_array_base", 0); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":977 + * + * cdef inline object get_array_base(ndarray arr): + * if arr.base is NULL: # <<<<<<<<<<<<<< + * return None + * else: + */ + __pyx_t_1 = ((__pyx_v_arr->base == NULL) != 0); + if (__pyx_t_1) { + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":978 + * cdef inline object get_array_base(ndarray arr): + * if arr.base is NULL: + * return None # <<<<<<<<<<<<<< + * else: + * return arr.base + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(Py_None); + __pyx_r = Py_None; + goto __pyx_L0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":977 + * + * cdef inline object get_array_base(ndarray arr): + * if arr.base is NULL: # <<<<<<<<<<<<<< + * return None + * else: + */ + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":980 + * return None + * else: + * return arr.base # <<<<<<<<<<<<<< + */ + /*else*/ { + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(((PyObject *)__pyx_v_arr->base)); + __pyx_r = ((PyObject *)__pyx_v_arr->base); + goto __pyx_L0; + } + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":976 + * arr.base = baseptr + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * if arr.base is NULL: + * return None + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef __pyx_moduledef = { + #if PY_VERSION_HEX < 0x03020000 + { PyObject_HEAD_INIT(NULL) NULL, 0, NULL }, + #else + PyModuleDef_HEAD_INIT, + #endif + "gpu_nms", + 0, /* m_doc */ + -1, /* m_size */ + __pyx_methods /* m_methods */, + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_s_D_v_zix_caffe_caffe_win_20160523, __pyx_k_D_v_zix_caffe_caffe_win_20160523, sizeof(__pyx_k_D_v_zix_caffe_caffe_win_20160523), 0, 0, 1, 0}, + {&__pyx_kp_u_Format_string_allocated_too_shor, __pyx_k_Format_string_allocated_too_shor, sizeof(__pyx_k_Format_string_allocated_too_shor), 0, 1, 0, 0}, + {&__pyx_kp_u_Format_string_allocated_too_shor_2, __pyx_k_Format_string_allocated_too_shor_2, sizeof(__pyx_k_Format_string_allocated_too_shor_2), 0, 1, 0, 0}, + {&__pyx_kp_u_Non_native_byte_order_not_suppor, __pyx_k_Non_native_byte_order_not_suppor, sizeof(__pyx_k_Non_native_byte_order_not_suppor), 0, 1, 0, 0}, + {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1}, + {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1}, + {&__pyx_n_s_argsort, __pyx_k_argsort, sizeof(__pyx_k_argsort), 0, 0, 1, 1}, + {&__pyx_n_s_boxes_dim, __pyx_k_boxes_dim, sizeof(__pyx_k_boxes_dim), 0, 0, 1, 1}, + {&__pyx_n_s_boxes_num, __pyx_k_boxes_num, sizeof(__pyx_k_boxes_num), 0, 0, 1, 1}, + {&__pyx_n_s_dets, __pyx_k_dets, sizeof(__pyx_k_dets), 0, 0, 1, 1}, + {&__pyx_n_s_device_id, __pyx_k_device_id, sizeof(__pyx_k_device_id), 0, 0, 1, 1}, + {&__pyx_n_s_dtype, __pyx_k_dtype, sizeof(__pyx_k_dtype), 0, 0, 1, 1}, + {&__pyx_n_s_gpu_nms, __pyx_k_gpu_nms, sizeof(__pyx_k_gpu_nms), 0, 0, 1, 1}, + {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, + {&__pyx_n_s_int32, __pyx_k_int32, sizeof(__pyx_k_int32), 0, 0, 1, 1}, + {&__pyx_n_s_keep, __pyx_k_keep, sizeof(__pyx_k_keep), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_kp_u_ndarray_is_not_C_contiguous, __pyx_k_ndarray_is_not_C_contiguous, sizeof(__pyx_k_ndarray_is_not_C_contiguous), 0, 1, 0, 0}, + {&__pyx_kp_u_ndarray_is_not_Fortran_contiguou, __pyx_k_ndarray_is_not_Fortran_contiguou, sizeof(__pyx_k_ndarray_is_not_Fortran_contiguou), 0, 1, 0, 0}, + {&__pyx_n_s_nms_gpu_nms, __pyx_k_nms_gpu_nms, sizeof(__pyx_k_nms_gpu_nms), 0, 0, 1, 1}, + {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, + {&__pyx_n_s_num_out, __pyx_k_num_out, sizeof(__pyx_k_num_out), 0, 0, 1, 1}, + {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, + {&__pyx_n_s_order, __pyx_k_order, sizeof(__pyx_k_order), 0, 0, 1, 1}, + {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, + {&__pyx_n_s_scores, __pyx_k_scores, sizeof(__pyx_k_scores), 0, 0, 1, 1}, + {&__pyx_n_s_sorted_dets, __pyx_k_sorted_dets, sizeof(__pyx_k_sorted_dets), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_thresh, __pyx_k_thresh, sizeof(__pyx_k_thresh), 0, 0, 1, 1}, + {&__pyx_kp_u_unknown_dtype_code_in_numpy_pxd, __pyx_k_unknown_dtype_code_in_numpy_pxd, sizeof(__pyx_k_unknown_dtype_code_in_numpy_pxd), 0, 1, 0, 0}, + {&__pyx_n_s_zeros, __pyx_k_zeros, sizeof(__pyx_k_zeros), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(1, 218, __pyx_L1_error) + __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(1, 231, __pyx_L1_error) + __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(1, 799, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "nms/gpu_nms.pyx":24 + * keep = np.zeros(boxes_num, dtype=np.int32) + * cdef np.ndarray[np.float32_t, ndim=1] \ + * scores = dets[:, 4] # <<<<<<<<<<<<<< + * #cdef np.ndarray[np.int_t, ndim=1] \ // 20160601, by xzn + * # order = scores.argsort()[::-1] + */ + __pyx_slice_ = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice_)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice_); + __Pyx_GIVEREF(__pyx_slice_); + __pyx_tuple__2 = PyTuple_Pack(2, __pyx_slice_, __pyx_int_4); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 24, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__2); + __Pyx_GIVEREF(__pyx_tuple__2); + + /* "nms/gpu_nms.pyx":28 + * # order = scores.argsort()[::-1] + * cdef np.ndarray[np.intp_t, ndim=1] \ + * order = scores.argsort()[::-1] # <<<<<<<<<<<<<< + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] + */ + __pyx_slice__3 = PySlice_New(Py_None, Py_None, __pyx_int_neg_1); if (unlikely(!__pyx_slice__3)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__3); + __Pyx_GIVEREF(__pyx_slice__3); + + /* "nms/gpu_nms.pyx":30 + * order = scores.argsort()[::-1] + * cdef np.ndarray[np.float32_t, ndim=2] \ + * sorted_dets = dets[order, :] # <<<<<<<<<<<<<< + * _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + * keep = keep[:num_out] + */ + __pyx_slice__4 = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice__4)) __PYX_ERR(0, 30, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__4); + __Pyx_GIVEREF(__pyx_slice__4); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":218 + * if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS) + * and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)): + * raise ValueError(u"ndarray is not C contiguous") # <<<<<<<<<<<<<< + * + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) + */ + __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_C_contiguous); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 218, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__5); + __Pyx_GIVEREF(__pyx_tuple__5); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":222 + * if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS) + * and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)): + * raise ValueError(u"ndarray is not Fortran contiguous") # <<<<<<<<<<<<<< + * + * info.buf = PyArray_DATA(self) + */ + __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_u_ndarray_is_not_Fortran_contiguou); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__6); + __Pyx_GIVEREF(__pyx_tuple__6); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":259 + * if ((descr.byteorder == c'>' and little_endian) or + * (descr.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< + * if t == NPY_BYTE: f = "b" + * elif t == NPY_UBYTE: f = "B" + */ + __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_u_Non_native_byte_order_not_suppor); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 259, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__7); + __Pyx_GIVEREF(__pyx_tuple__7); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":799 + * + * if (end - f) - (new_offset - offset[0]) < 15: + * raise RuntimeError(u"Format string allocated too short, see comment in numpy.pxd") # <<<<<<<<<<<<<< + * + * if ((child.byteorder == c'>' and little_endian) or + */ + __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 799, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__8); + __Pyx_GIVEREF(__pyx_tuple__8); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":803 + * if ((child.byteorder == c'>' and little_endian) or + * (child.byteorder == c'<' and not little_endian)): + * raise ValueError(u"Non-native byte order not supported") # <<<<<<<<<<<<<< + * # One could encode it in the format string and have Cython + * # complain instead, BUT: < and > in format strings also imply + */ + __pyx_tuple__9 = PyTuple_Pack(1, __pyx_kp_u_Non_native_byte_order_not_suppor); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 803, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__9); + __Pyx_GIVEREF(__pyx_tuple__9); + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":823 + * t = child.type_num + * if end - f < 5: + * raise RuntimeError(u"Format string allocated too short.") # <<<<<<<<<<<<<< + * + * # Until ticket #99 is fixed, use integers to avoid warnings + */ + __pyx_tuple__10 = PyTuple_Pack(1, __pyx_kp_u_Format_string_allocated_too_shor_2); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(1, 823, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__10); + __Pyx_GIVEREF(__pyx_tuple__10); + + /* "nms/gpu_nms.pyx":16 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + __pyx_tuple__11 = PyTuple_Pack(10, __pyx_n_s_dets, __pyx_n_s_thresh, __pyx_n_s_device_id, __pyx_n_s_boxes_num, __pyx_n_s_boxes_dim, __pyx_n_s_num_out, __pyx_n_s_keep, __pyx_n_s_scores, __pyx_n_s_order, __pyx_n_s_sorted_dets); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__11); + __Pyx_GIVEREF(__pyx_tuple__11); + __pyx_codeobj__12 = (PyObject*)__Pyx_PyCode_New(3, 0, 10, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__11, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_D_v_zix_caffe_caffe_win_20160523, __pyx_n_s_gpu_nms, 16, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__12)) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_4 = PyInt_FromLong(4); if (unlikely(!__pyx_int_4)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +#if PY_MAJOR_VERSION < 3 +PyMODINIT_FUNC initgpu_nms(void); /*proto*/ +PyMODINIT_FUNC initgpu_nms(void) +#else +PyMODINIT_FUNC PyInit_gpu_nms(void); /*proto*/ +PyMODINIT_FUNC PyInit_gpu_nms(void) +#endif +{ + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannyDeclarations + #if CYTHON_REFNANNY + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); + if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); + } + #endif + __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_gpu_nms(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + #ifdef WITH_THREAD /* Python build with threading support? */ + PyEval_InitThreads(); + #endif + #endif + /*--- Module creation code ---*/ + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("gpu_nms", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + #if CYTHON_COMPILING_IN_PYPY + Py_INCREF(__pyx_b); + #endif + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main_nms__gpu_nms) { + if (PyObject_SetAttrString(__pyx_m, "__name__", __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "nms.gpu_nms")) { + if (unlikely(PyDict_SetItemString(modules, "nms.gpu_nms", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global init code ---*/ + /*--- Variable export code ---*/ + /*--- Function export code ---*/ + /*--- Type init code ---*/ + /*--- Type import code ---*/ + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__Pyx_BUILTIN_MODULE_NAME, "type", + #if CYTHON_COMPILING_IN_PYPY + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + 0); if (unlikely(!__pyx_ptype_7cpython_4type_type)) __PYX_ERR(2, 9, __pyx_L1_error) + __pyx_ptype_5numpy_dtype = __Pyx_ImportType("numpy", "dtype", sizeof(PyArray_Descr), 0); if (unlikely(!__pyx_ptype_5numpy_dtype)) __PYX_ERR(1, 155, __pyx_L1_error) + __pyx_ptype_5numpy_flatiter = __Pyx_ImportType("numpy", "flatiter", sizeof(PyArrayIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_flatiter)) __PYX_ERR(1, 168, __pyx_L1_error) + __pyx_ptype_5numpy_broadcast = __Pyx_ImportType("numpy", "broadcast", sizeof(PyArrayMultiIterObject), 0); if (unlikely(!__pyx_ptype_5numpy_broadcast)) __PYX_ERR(1, 172, __pyx_L1_error) + __pyx_ptype_5numpy_ndarray = __Pyx_ImportType("numpy", "ndarray", sizeof(PyArrayObject), 0); if (unlikely(!__pyx_ptype_5numpy_ndarray)) __PYX_ERR(1, 181, __pyx_L1_error) + __pyx_ptype_5numpy_ufunc = __Pyx_ImportType("numpy", "ufunc", sizeof(PyUFuncObject), 0); if (unlikely(!__pyx_ptype_5numpy_ufunc)) __PYX_ERR(1, 861, __pyx_L1_error) + /*--- Variable import code ---*/ + /*--- Function import code ---*/ + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "nms/gpu_nms.pyx":8 + * # -------------------------------------------------------- + * + * import numpy as np # <<<<<<<<<<<<<< + * cimport numpy as np + * + */ + __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "nms/gpu_nms.pyx":11 + * cimport numpy as np + * + * assert sizeof(int) == sizeof(np.int32_t) # <<<<<<<<<<<<<< + * + * cdef extern from "gpu_nms.hpp": + */ + #ifndef CYTHON_WITHOUT_ASSERTIONS + if (unlikely(!Py_OptimizeFlag)) { + if (unlikely(!(((sizeof(int)) == (sizeof(__pyx_t_5numpy_int32_t))) != 0))) { + PyErr_SetNone(PyExc_AssertionError); + __PYX_ERR(0, 11, __pyx_L1_error) + } + } + #endif + + /* "nms/gpu_nms.pyx":16 + * void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + * + * def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, # <<<<<<<<<<<<<< + * np.int32_t device_id=0): + * cdef int boxes_num = dets.shape[0] + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_3nms_7gpu_nms_1gpu_nms, NULL, __pyx_n_s_nms_gpu_nms); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_gpu_nms, __pyx_t_1) < 0) __PYX_ERR(0, 16, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "nms/gpu_nms.pyx":1 + * # -------------------------------------------------------- # <<<<<<<<<<<<<< + * # Faster R-CNN + * # Copyright (c) 2015 Microsoft + */ + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "C:/Anaconda2/lib/site-packages/Cython/Includes/numpy/__init__.pxd":976 + * arr.base = baseptr + * + * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< + * if arr.base is NULL: + * return None + */ + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init nms.gpu_nms", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_DECREF(__pyx_m); __pyx_m = 0; + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init nms.gpu_nms"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if PY_MAJOR_VERSION < 3 + return; + #else + return __pyx_m; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule((char *)modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* ArgTypeTest */ +static void __Pyx_RaiseArgumentTypeInvalid(const char* name, PyObject *obj, PyTypeObject *type) { + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); +} +static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact) +{ + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + if (none_allowed && obj == Py_None) return 1; + else if (exact) { + if (likely(Py_TYPE(obj) == type)) return 1; + #if PY_MAJOR_VERSION == 2 + else if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; + #endif + } + else { + if (likely(PyObject_TypeCheck(obj, type))) return 1; + } + __Pyx_RaiseArgumentTypeInvalid(name, obj, type); + return 0; +} + +/* BufferFormatCheck */ +static CYTHON_INLINE int __Pyx_IsLittleEndian(void) { + unsigned int n = 1; + return *(unsigned char*)(&n) != 0; +} +static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, + __Pyx_BufFmt_StackElem* stack, + __Pyx_TypeInfo* type) { + stack[0].field = &ctx->root; + stack[0].parent_offset = 0; + ctx->root.type = type; + ctx->root.name = "buffer dtype"; + ctx->root.offset = 0; + ctx->head = stack; + ctx->head->field = &ctx->root; + ctx->fmt_offset = 0; + ctx->head->parent_offset = 0; + ctx->new_packmode = '@'; + ctx->enc_packmode = '@'; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->is_complex = 0; + ctx->is_valid_array = 0; + ctx->struct_alignment = 0; + while (type->typegroup == 'S') { + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = 0; + type = type->fields->type; + } +} +static int __Pyx_BufFmt_ParseNumber(const char** ts) { + int count; + const char* t = *ts; + if (*t < '0' || *t > '9') { + return -1; + } else { + count = *t++ - '0'; + while (*t >= '0' && *t < '9') { + count *= 10; + count += *t++ - '0'; + } + } + *ts = t; + return count; +} +static int __Pyx_BufFmt_ExpectNumber(const char **ts) { + int number = __Pyx_BufFmt_ParseNumber(ts); + if (number == -1) + PyErr_Format(PyExc_ValueError,\ + "Does not understand character buffer dtype format string ('%c')", **ts); + return number; +} +static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { + PyErr_Format(PyExc_ValueError, + "Unexpected format string character: '%c'", ch); +} +static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { + switch (ch) { + case 'c': return "'char'"; + case 'b': return "'signed char'"; + case 'B': return "'unsigned char'"; + case 'h': return "'short'"; + case 'H': return "'unsigned short'"; + case 'i': return "'int'"; + case 'I': return "'unsigned int'"; + case 'l': return "'long'"; + case 'L': return "'unsigned long'"; + case 'q': return "'long long'"; + case 'Q': return "'unsigned long long'"; + case 'f': return (is_complex ? "'complex float'" : "'float'"); + case 'd': return (is_complex ? "'complex double'" : "'double'"); + case 'g': return (is_complex ? "'complex long double'" : "'long double'"); + case 'T': return "a struct"; + case 'O': return "Python object"; + case 'P': return "a pointer"; + case 's': case 'p': return "a string"; + case 0: return "end"; + default: return "unparseable format string"; + } +} +static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return 2; + case 'i': case 'I': case 'l': case 'L': return 4; + case 'q': case 'Q': return 8; + case 'f': return (is_complex ? 8 : 4); + case 'd': return (is_complex ? 16 : 8); + case 'g': { + PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); + return 0; + } + case 'O': case 'P': return sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { + switch (ch) { + case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(short); + case 'i': case 'I': return sizeof(int); + case 'l': case 'L': return sizeof(long); + #ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(PY_LONG_LONG); + #endif + case 'f': return sizeof(float) * (is_complex ? 2 : 1); + case 'd': return sizeof(double) * (is_complex ? 2 : 1); + case 'g': return sizeof(long double) * (is_complex ? 2 : 1); + case 'O': case 'P': return sizeof(void*); + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +typedef struct { char c; short x; } __Pyx_st_short; +typedef struct { char c; int x; } __Pyx_st_int; +typedef struct { char c; long x; } __Pyx_st_long; +typedef struct { char c; float x; } __Pyx_st_float; +typedef struct { char c; double x; } __Pyx_st_double; +typedef struct { char c; long double x; } __Pyx_st_longdouble; +typedef struct { char c; void *x; } __Pyx_st_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; +#endif +static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_st_float) - sizeof(float); + case 'd': return sizeof(__Pyx_st_double) - sizeof(double); + case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +/* These are for computing the padding at the end of the struct to align + on the first member of the struct. This will probably the same as above, + but we don't have any guarantees. + */ +typedef struct { short x; char c; } __Pyx_pad_short; +typedef struct { int x; char c; } __Pyx_pad_int; +typedef struct { long x; char c; } __Pyx_pad_long; +typedef struct { float x; char c; } __Pyx_pad_float; +typedef struct { double x; char c; } __Pyx_pad_double; +typedef struct { long double x; char c; } __Pyx_pad_longdouble; +typedef struct { void *x; char c; } __Pyx_pad_void_p; +#ifdef HAVE_LONG_LONG +typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; +#endif +static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) { + switch (ch) { + case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; + case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); + case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); + case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); +#ifdef HAVE_LONG_LONG + case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); +#endif + case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); + case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); + case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); + case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); + default: + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } +} +static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { + switch (ch) { + case 'c': + return 'H'; + case 'b': case 'h': case 'i': + case 'l': case 'q': case 's': case 'p': + return 'I'; + case 'B': case 'H': case 'I': case 'L': case 'Q': + return 'U'; + case 'f': case 'd': case 'g': + return (is_complex ? 'C' : 'R'); + case 'O': + return 'O'; + case 'P': + return 'P'; + default: { + __Pyx_BufFmt_RaiseUnexpectedChar(ch); + return 0; + } + } +} +static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { + if (ctx->head == NULL || ctx->head->field == &ctx->root) { + const char* expected; + const char* quote; + if (ctx->head == NULL) { + expected = "end"; + quote = ""; + } else { + expected = ctx->head->field->type->name; + quote = "'"; + } + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected %s%s%s but got %s", + quote, expected, quote, + __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); + } else { + __Pyx_StructField* field = ctx->head->field; + __Pyx_StructField* parent = (ctx->head - 1)->field; + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", + field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), + parent->type->name, field->name); + } +} +static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { + char group; + size_t size, offset, arraysize = 1; + if (ctx->enc_type == 0) return 0; + if (ctx->head->field->type->arraysize[0]) { + int i, ndim = 0; + if (ctx->enc_type == 's' || ctx->enc_type == 'p') { + ctx->is_valid_array = ctx->head->field->type->ndim == 1; + ndim = 1; + if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { + PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %zu", + ctx->head->field->type->arraysize[0], ctx->enc_count); + return -1; + } + } + if (!ctx->is_valid_array) { + PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", + ctx->head->field->type->ndim, ndim); + return -1; + } + for (i = 0; i < ctx->head->field->type->ndim; i++) { + arraysize *= ctx->head->field->type->arraysize[i]; + } + ctx->is_valid_array = 0; + ctx->enc_count = 1; + } + group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); + do { + __Pyx_StructField* field = ctx->head->field; + __Pyx_TypeInfo* type = field->type; + if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { + size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); + } else { + size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); + } + if (ctx->enc_packmode == '@') { + size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); + size_t align_mod_offset; + if (align_at == 0) return -1; + align_mod_offset = ctx->fmt_offset % align_at; + if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; + if (ctx->struct_alignment == 0) + ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, + ctx->is_complex); + } + if (type->size != size || type->typegroup != group) { + if (type->typegroup == 'C' && type->fields != NULL) { + size_t parent_offset = ctx->head->parent_offset + field->offset; + ++ctx->head; + ctx->head->field = type->fields; + ctx->head->parent_offset = parent_offset; + continue; + } + if ((type->typegroup == 'H' || group == 'H') && type->size == size) { + } else { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + } + offset = ctx->head->parent_offset + field->offset; + if (ctx->fmt_offset != offset) { + PyErr_Format(PyExc_ValueError, + "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", + (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); + return -1; + } + ctx->fmt_offset += size; + if (arraysize) + ctx->fmt_offset += (arraysize - 1) * size; + --ctx->enc_count; + while (1) { + if (field == &ctx->root) { + ctx->head = NULL; + if (ctx->enc_count != 0) { + __Pyx_BufFmt_RaiseExpected(ctx); + return -1; + } + break; + } + ctx->head->field = ++field; + if (field->type == NULL) { + --ctx->head; + field = ctx->head->field; + continue; + } else if (field->type->typegroup == 'S') { + size_t parent_offset = ctx->head->parent_offset + field->offset; + if (field->type->fields->type == NULL) continue; + field = field->type->fields; + ++ctx->head; + ctx->head->field = field; + ctx->head->parent_offset = parent_offset; + break; + } else { + break; + } + } + } while (ctx->enc_count); + ctx->enc_type = 0; + ctx->is_complex = 0; + return 0; +} +static CYTHON_INLINE PyObject * +__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) +{ + const char *ts = *tsp; + int i = 0, number; + int ndim = ctx->head->field->type->ndim; +; + ++ts; + if (ctx->new_count != 1) { + PyErr_SetString(PyExc_ValueError, + "Cannot handle repeated arrays in format string"); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + while (*ts && *ts != ')') { + switch (*ts) { + case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; + default: break; + } + number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return NULL; + if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) + return PyErr_Format(PyExc_ValueError, + "Expected a dimension of size %zu, got %d", + ctx->head->field->type->arraysize[i], number); + if (*ts != ',' && *ts != ')') + return PyErr_Format(PyExc_ValueError, + "Expected a comma in format string, got '%c'", *ts); + if (*ts == ',') ts++; + i++; + } + if (i != ndim) + return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", + ctx->head->field->type->ndim, i); + if (!*ts) { + PyErr_SetString(PyExc_ValueError, + "Unexpected end of format string, expected ')'"); + return NULL; + } + ctx->is_valid_array = 1; + ctx->new_count = 1; + *tsp = ++ts; + return Py_None; +} +static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { + int got_Z = 0; + while (1) { + switch(*ts) { + case 0: + if (ctx->enc_type != 0 && ctx->head == NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + if (ctx->head != NULL) { + __Pyx_BufFmt_RaiseExpected(ctx); + return NULL; + } + return ts; + case ' ': + case '\r': + case '\n': + ++ts; + break; + case '<': + if (!__Pyx_IsLittleEndian()) { + PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '>': + case '!': + if (__Pyx_IsLittleEndian()) { + PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); + return NULL; + } + ctx->new_packmode = '='; + ++ts; + break; + case '=': + case '@': + case '^': + ctx->new_packmode = *ts++; + break; + case 'T': + { + const char* ts_after_sub; + size_t i, struct_count = ctx->new_count; + size_t struct_alignment = ctx->struct_alignment; + ctx->new_count = 1; + ++ts; + if (*ts != '{') { + PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); + return NULL; + } + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + ctx->enc_count = 0; + ctx->struct_alignment = 0; + ++ts; + ts_after_sub = ts; + for (i = 0; i != struct_count; ++i) { + ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); + if (!ts_after_sub) return NULL; + } + ts = ts_after_sub; + if (struct_alignment) ctx->struct_alignment = struct_alignment; + } + break; + case '}': + { + size_t alignment = ctx->struct_alignment; + ++ts; + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_type = 0; + if (alignment && ctx->fmt_offset % alignment) { + ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); + } + } + return ts; + case 'x': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->fmt_offset += ctx->new_count; + ctx->new_count = 1; + ctx->enc_count = 0; + ctx->enc_type = 0; + ctx->enc_packmode = ctx->new_packmode; + ++ts; + break; + case 'Z': + got_Z = 1; + ++ts; + if (*ts != 'f' && *ts != 'd' && *ts != 'g') { + __Pyx_BufFmt_RaiseUnexpectedChar('Z'); + return NULL; + } + case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': + case 'l': case 'L': case 'q': case 'Q': + case 'f': case 'd': case 'g': + case 'O': case 'p': + if (ctx->enc_type == *ts && got_Z == ctx->is_complex && + ctx->enc_packmode == ctx->new_packmode) { + ctx->enc_count += ctx->new_count; + ctx->new_count = 1; + got_Z = 0; + ++ts; + break; + } + case 's': + if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; + ctx->enc_count = ctx->new_count; + ctx->enc_packmode = ctx->new_packmode; + ctx->enc_type = *ts; + ctx->is_complex = got_Z; + ++ts; + ctx->new_count = 1; + got_Z = 0; + break; + case ':': + ++ts; + while(*ts != ':') ++ts; + ++ts; + break; + case '(': + if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL; + break; + default: + { + int number = __Pyx_BufFmt_ExpectNumber(&ts); + if (number == -1) return NULL; + ctx->new_count = (size_t)number; + } + } + } +} +static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) { + buf->buf = NULL; + buf->obj = NULL; + buf->strides = __Pyx_zeros; + buf->shape = __Pyx_zeros; + buf->suboffsets = __Pyx_minusones; +} +static CYTHON_INLINE int __Pyx_GetBufferAndValidate( + Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, + int nd, int cast, __Pyx_BufFmt_StackElem* stack) +{ + if (obj == Py_None || obj == NULL) { + __Pyx_ZeroBuffer(buf); + return 0; + } + buf->buf = NULL; + if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail; + if (buf->ndim != nd) { + PyErr_Format(PyExc_ValueError, + "Buffer has wrong number of dimensions (expected %d, got %d)", + nd, buf->ndim); + goto fail; + } + if (!cast) { + __Pyx_BufFmt_Context ctx; + __Pyx_BufFmt_Init(&ctx, stack, dtype); + if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; + } + if ((unsigned)buf->itemsize != dtype->size) { + PyErr_Format(PyExc_ValueError, + "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", + buf->itemsize, (buf->itemsize > 1) ? "s" : "", + dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); + goto fail; + } + if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; + return 0; +fail:; + __Pyx_ZeroBuffer(buf); + return -1; +} +static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { + if (info->buf == NULL) return; + if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; + __Pyx_ReleaseBuffer(info); +} + +/* GetBuiltinName */ + static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* GetModuleGlobalName */ + static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) { + PyObject *result; +#if CYTHON_COMPILING_IN_CPYTHON + result = PyDict_GetItem(__pyx_d, name); + if (likely(result)) { + Py_INCREF(result); + } else { +#else + result = PyObject_GetItem(__pyx_d, name); + if (!result) { + PyErr_Clear(); +#endif + result = __Pyx_GetBuiltinName(name); + } + return result; +} + +/* PyObjectCall */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = func->ob_type->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* ExtTypeTest */ + static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); + return 0; + } + if (likely(PyObject_TypeCheck(obj, type))) + return 1; + PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", + Py_TYPE(obj)->tp_name, type->tp_name); + return 0; +} + +/* PyObjectCallMethO */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallOneArg */ + #if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || PyObject_TypeCheck(func, __pyx_CyFunctionType))) { +#else + if (likely(PyCFunction_Check(func))) { +#endif + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyObjectCallNoArg */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || PyObject_TypeCheck(func, __pyx_CyFunctionType))) { +#else + if (likely(PyCFunction_Check(func))) { +#endif + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + +/* BufferIndexError */ + static void __Pyx_RaiseBufferIndexError(int axis) { + PyErr_Format(PyExc_IndexError, + "Out of bounds on buffer access (axis %d)", axis); +} + +/* SliceObject */ + static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, + Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice, + int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) { +#if CYTHON_COMPILING_IN_CPYTHON + PyMappingMethods* mp; +#if PY_MAJOR_VERSION < 3 + PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence; + if (likely(ms && ms->sq_slice)) { + if (!has_cstart) { + if (_py_start && (*_py_start != Py_None)) { + cstart = __Pyx_PyIndex_AsSsize_t(*_py_start); + if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstart = 0; + } + if (!has_cstop) { + if (_py_stop && (*_py_stop != Py_None)) { + cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop); + if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstop = PY_SSIZE_T_MAX; + } + if (wraparound && unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { + Py_ssize_t l = ms->sq_length(obj); + if (likely(l >= 0)) { + if (cstop < 0) { + cstop += l; + if (cstop < 0) cstop = 0; + } + if (cstart < 0) { + cstart += l; + if (cstart < 0) cstart = 0; + } + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + goto bad; + PyErr_Clear(); + } + } + return ms->sq_slice(obj, cstart, cstop); + } +#endif + mp = Py_TYPE(obj)->tp_as_mapping; + if (likely(mp && mp->mp_subscript)) +#endif + { + PyObject* result; + PyObject *py_slice, *py_start, *py_stop; + if (_py_slice) { + py_slice = *_py_slice; + } else { + PyObject* owned_start = NULL; + PyObject* owned_stop = NULL; + if (_py_start) { + py_start = *_py_start; + } else { + if (has_cstart) { + owned_start = py_start = PyInt_FromSsize_t(cstart); + if (unlikely(!py_start)) goto bad; + } else + py_start = Py_None; + } + if (_py_stop) { + py_stop = *_py_stop; + } else { + if (has_cstop) { + owned_stop = py_stop = PyInt_FromSsize_t(cstop); + if (unlikely(!py_stop)) { + Py_XDECREF(owned_start); + goto bad; + } + } else + py_stop = Py_None; + } + py_slice = PySlice_New(py_start, py_stop, Py_None); + Py_XDECREF(owned_start); + Py_XDECREF(owned_stop); + if (unlikely(!py_slice)) goto bad; + } +#if CYTHON_COMPILING_IN_CPYTHON + result = mp->mp_subscript(obj, py_slice); +#else + result = PyObject_GetItem(obj, py_slice); +#endif + if (!_py_slice) { + Py_DECREF(py_slice); + } + return result; + } + PyErr_Format(PyExc_TypeError, + "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name); +bad: + return NULL; +} + +/* BufferFallbackError */ + static void __Pyx_RaiseBufferFallbackError(void) { + PyErr_SetString(PyExc_ValueError, + "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!"); +} + +/* PyErrFetchRestore */ + #if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* RaiseException */ + #if PY_MAJOR_VERSION < 3 +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, + CYTHON_UNUSED PyObject *cause) { + __Pyx_PyThreadState_declare + Py_XINCREF(type); + if (!value || value == Py_None) + value = NULL; + else + Py_INCREF(value); + if (!tb || tb == Py_None) + tb = NULL; + else { + Py_INCREF(tb); + if (!PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto raise_error; + } + } + if (PyType_Check(type)) { +#if CYTHON_COMPILING_IN_PYPY + if (!value) { + Py_INCREF(Py_None); + value = Py_None; + } +#endif + PyErr_NormalizeException(&type, &value, &tb); + } else { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto raise_error; + } + value = type; + type = (PyObject*) Py_TYPE(type); + Py_INCREF(type); + if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto raise_error; + } + } + __Pyx_PyThreadState_assign + __Pyx_ErrRestore(type, value, tb); + return; +raise_error: + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(tb); + return; +} +#else +static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { + PyObject* owned_instance = NULL; + if (tb == Py_None) { + tb = 0; + } else if (tb && !PyTraceBack_Check(tb)) { + PyErr_SetString(PyExc_TypeError, + "raise: arg 3 must be a traceback or None"); + goto bad; + } + if (value == Py_None) + value = 0; + if (PyExceptionInstance_Check(type)) { + if (value) { + PyErr_SetString(PyExc_TypeError, + "instance exception may not have a separate value"); + goto bad; + } + value = type; + type = (PyObject*) Py_TYPE(value); + } else if (PyExceptionClass_Check(type)) { + PyObject *instance_class = NULL; + if (value && PyExceptionInstance_Check(value)) { + instance_class = (PyObject*) Py_TYPE(value); + if (instance_class != type) { + int is_subclass = PyObject_IsSubclass(instance_class, type); + if (!is_subclass) { + instance_class = NULL; + } else if (unlikely(is_subclass == -1)) { + goto bad; + } else { + type = instance_class; + } + } + } + if (!instance_class) { + PyObject *args; + if (!value) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } else + args = PyTuple_Pack(1, value); + if (!args) + goto bad; + owned_instance = PyObject_Call(type, args, NULL); + Py_DECREF(args); + if (!owned_instance) + goto bad; + value = owned_instance; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto bad; + } + } + } else { + PyErr_SetString(PyExc_TypeError, + "raise: exception class must be a subclass of BaseException"); + goto bad; + } +#if PY_VERSION_HEX >= 0x03030000 + if (cause) { +#else + if (cause && cause != Py_None) { +#endif + PyObject *fixed_cause; + if (cause == Py_None) { + fixed_cause = NULL; + } else if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto bad; + } else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + Py_INCREF(fixed_cause); + } else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto bad; + } + PyException_SetCause(value, fixed_cause); + } + PyErr_SetObject(type, value); + if (tb) { +#if CYTHON_COMPILING_IN_PYPY + PyObject *tmp_type, *tmp_value, *tmp_tb; + PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); + Py_INCREF(tb); + PyErr_Restore(tmp_type, tmp_value, tb); + Py_XDECREF(tmp_tb); +#else + PyThreadState *tstate = PyThreadState_GET(); + PyObject* tmp_tb = tstate->curexc_traceback; + if (tb != tmp_tb) { + Py_INCREF(tb); + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_tb); + } +#endif + } +bad: + Py_XDECREF(owned_instance); + return; +} +#endif + +/* RaiseTooManyValuesToUnpack */ + static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); +} + +/* RaiseNeedMoreValuesToUnpack */ + static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", + index, (index == 1) ? "" : "s"); +} + +/* RaiseNoneIterError */ + static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); +} + +/* Import */ + static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { + PyObject *empty_list = 0; + PyObject *module = 0; + PyObject *global_dict = 0; + PyObject *empty_dict = 0; + PyObject *list; + #if PY_VERSION_HEX < 0x03030000 + PyObject *py_import; + py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); + if (!py_import) + goto bad; + #endif + if (from_list) + list = from_list; + else { + empty_list = PyList_New(0); + if (!empty_list) + goto bad; + list = empty_list; + } + global_dict = PyModule_GetDict(__pyx_m); + if (!global_dict) + goto bad; + empty_dict = PyDict_New(); + if (!empty_dict) + goto bad; + { + #if PY_MAJOR_VERSION >= 3 + if (level == -1) { + if (strchr(__Pyx_MODULE_NAME, '.')) { + #if PY_VERSION_HEX < 0x03030000 + PyObject *py_level = PyInt_FromLong(1); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, 1); + #endif + if (!module) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + goto bad; + PyErr_Clear(); + } + } + level = 0; + } + #endif + if (!module) { + #if PY_VERSION_HEX < 0x03030000 + PyObject *py_level = PyInt_FromLong(level); + if (!py_level) + goto bad; + module = PyObject_CallFunctionObjArgs(py_import, + name, global_dict, empty_dict, list, py_level, NULL); + Py_DECREF(py_level); + #else + module = PyImport_ImportModuleLevelObject( + name, global_dict, empty_dict, list, level); + #endif + } + } +bad: + #if PY_VERSION_HEX < 0x03030000 + Py_XDECREF(py_import); + #endif + Py_XDECREF(empty_list); + Py_XDECREF(empty_dict); + return module; +} + +/* CodeObjectCache */ + static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ + #include "compile.h" +#include "frameobject.h" +#include "traceback.h" +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + #if PY_MAJOR_VERSION < 3 + py_srcfile = PyString_FromString(filename); + #else + py_srcfile = PyUnicode_FromString(filename); + #endif + if (!py_srcfile) goto bad; + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif + } + if (!py_funcname) goto bad; + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + Py_DECREF(py_funcname); + return py_code; +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + py_code = __pyx_find_code_object(c_line ? c_line : py_line); + if (!py_code) { + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) goto bad; + __pyx_insert_code_object(c_line ? c_line : py_line, py_code); + } + py_frame = PyFrame_New( + PyThreadState_GET(), /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + py_frame->f_lineno = py_line; + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +#if PY_MAJOR_VERSION < 3 +static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { + if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); + if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags); + PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name); + return -1; +} +static void __Pyx_ReleaseBuffer(Py_buffer *view) { + PyObject *obj = view->obj; + if (!obj) return; + if (PyObject_CheckBuffer(obj)) { + PyBuffer_Release(view); + return; + } + if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) { __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); return; } + Py_DECREF(obj); + view->obj = NULL; +} +#endif + + + /* CIntFromPyVerify */ + #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { + const int neg_one = (int) -1, const_zero = (int) 0; + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + } +} + +/* None */ + #if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return ::std::complex< float >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + return x + y*(__pyx_t_float_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { + __pyx_t_float_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +/* None */ + #if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eqf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sumf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_difff(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prodf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quotf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + float denom = b.real * b.real + b.imag * b.imag; + z.real = (a.real * b.real + a.imag * b.imag) / denom; + z.imag = (a.imag * b.real - a.real * b.imag) / denom; + return z; + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_negf(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zerof(__pyx_t_float_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conjf(__pyx_t_float_complex a) { + __pyx_t_float_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE float __Pyx_c_absf(__pyx_t_float_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrtf(z.real*z.real + z.imag*z.imag); + #else + return hypotf(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_powf(__pyx_t_float_complex a, __pyx_t_float_complex b) { + __pyx_t_float_complex z; + float r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + float denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + z = __Pyx_c_prodf(a, a); + return __Pyx_c_prodf(a, a); + case 3: + z = __Pyx_c_prodf(a, a); + return __Pyx_c_prodf(z, a); + case 4: + z = __Pyx_c_prodf(a, a); + return __Pyx_c_prodf(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } + r = a.real; + theta = 0; + } else { + r = __Pyx_c_absf(a); + theta = atan2f(a.imag, a.real); + } + lnr = logf(r); + z_r = expf(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cosf(z_theta); + z.imag = z_r * sinf(z_theta); + return z; + } + #endif +#endif + +/* None */ + #if CYTHON_CCOMPLEX + #ifdef __cplusplus + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return ::std::complex< double >(x, y); + } + #else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + return x + y*(__pyx_t_double_complex)_Complex_I; + } + #endif +#else + static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { + __pyx_t_double_complex z; + z.real = x; + z.imag = y; + return z; + } +#endif + +/* None */ + #if CYTHON_CCOMPLEX +#else + static CYTHON_INLINE int __Pyx_c_eq(__pyx_t_double_complex a, __pyx_t_double_complex b) { + return (a.real == b.real) && (a.imag == b.imag); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real + b.real; + z.imag = a.imag + b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real - b.real; + z.imag = a.imag - b.imag; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + z.real = a.real * b.real - a.imag * b.imag; + z.imag = a.real * b.imag + a.imag * b.real; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + double denom = b.real * b.real + b.imag * b.imag; + z.real = (a.real * b.real + a.imag * b.imag) / denom; + z.imag = (a.imag * b.real - a.real * b.imag) / denom; + return z; + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = -a.real; + z.imag = -a.imag; + return z; + } + static CYTHON_INLINE int __Pyx_c_is_zero(__pyx_t_double_complex a) { + return (a.real == 0) && (a.imag == 0); + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj(__pyx_t_double_complex a) { + __pyx_t_double_complex z; + z.real = a.real; + z.imag = -a.imag; + return z; + } + #if 1 + static CYTHON_INLINE double __Pyx_c_abs(__pyx_t_double_complex z) { + #if !defined(HAVE_HYPOT) || defined(_MSC_VER) + return sqrt(z.real*z.real + z.imag*z.imag); + #else + return hypot(z.real, z.imag); + #endif + } + static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow(__pyx_t_double_complex a, __pyx_t_double_complex b) { + __pyx_t_double_complex z; + double r, lnr, theta, z_r, z_theta; + if (b.imag == 0 && b.real == (int)b.real) { + if (b.real < 0) { + double denom = a.real * a.real + a.imag * a.imag; + a.real = a.real / denom; + a.imag = -a.imag / denom; + b.real = -b.real; + } + switch ((int)b.real) { + case 0: + z.real = 1; + z.imag = 0; + return z; + case 1: + return a; + case 2: + z = __Pyx_c_prod(a, a); + return __Pyx_c_prod(a, a); + case 3: + z = __Pyx_c_prod(a, a); + return __Pyx_c_prod(z, a); + case 4: + z = __Pyx_c_prod(a, a); + return __Pyx_c_prod(z, z); + } + } + if (a.imag == 0) { + if (a.real == 0) { + return a; + } + r = a.real; + theta = 0; + } else { + r = __Pyx_c_abs(a); + theta = atan2(a.imag, a.real); + } + lnr = log(r); + z_r = exp(lnr * b.real - theta * b.imag); + z_theta = theta * b.real + lnr * b.imag; + z.real = z_r * cos(z_theta); + z.imag = z_r * sin(z_theta); + return z; + } + #endif +#endif + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__NPY_TYPES(enum NPY_TYPES value) { + const enum NPY_TYPES neg_one = (enum NPY_TYPES) -1, const_zero = (enum NPY_TYPES) 0; + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(enum NPY_TYPES) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); + } else if (sizeof(enum NPY_TYPES) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); + } + } else { + if (sizeof(enum NPY_TYPES) <= sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(enum NPY_TYPES) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(enum NPY_TYPES), + little, !is_unsigned); + } +} + +/* CIntFromPy */ + static CYTHON_INLINE npy_int32 __Pyx_PyInt_As_npy_int32(PyObject *x) { + const npy_int32 neg_one = (npy_int32) -1, const_zero = (npy_int32) 0; + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(npy_int32) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (npy_int32) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (npy_int32) 0; + case 1: __PYX_VERIFY_RETURN_INT(npy_int32, digit, digits[0]) + case 2: + if (8 * sizeof(npy_int32) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) >= 2 * PyLong_SHIFT) { + return (npy_int32) (((((npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(npy_int32) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) >= 3 * PyLong_SHIFT) { + return (npy_int32) (((((((npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(npy_int32) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) >= 4 * PyLong_SHIFT) { + return (npy_int32) (((((((((npy_int32)digits[3]) << PyLong_SHIFT) | (npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (npy_int32) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(npy_int32) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, unsigned long, PyLong_AsUnsignedLong(x)) + } else if (sizeof(npy_int32) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (npy_int32) 0; + case -1: __PYX_VERIFY_RETURN_INT(npy_int32, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(npy_int32, digit, +digits[0]) + case -2: + if (8 * sizeof(npy_int32) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 2 * PyLong_SHIFT) { + return (npy_int32) (((npy_int32)-1)*(((((npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(npy_int32) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 2 * PyLong_SHIFT) { + return (npy_int32) ((((((npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(npy_int32) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 3 * PyLong_SHIFT) { + return (npy_int32) (((npy_int32)-1)*(((((((npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(npy_int32) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 3 * PyLong_SHIFT) { + return (npy_int32) ((((((((npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(npy_int32) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 4 * PyLong_SHIFT) { + return (npy_int32) (((npy_int32)-1)*(((((((((npy_int32)digits[3]) << PyLong_SHIFT) | (npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(npy_int32) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(npy_int32, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(npy_int32) - 1 > 4 * PyLong_SHIFT) { + return (npy_int32) ((((((((((npy_int32)digits[3]) << PyLong_SHIFT) | (npy_int32)digits[2]) << PyLong_SHIFT) | (npy_int32)digits[1]) << PyLong_SHIFT) | (npy_int32)digits[0]))); + } + } + break; + } +#endif + if (sizeof(npy_int32) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, long, PyLong_AsLong(x)) + } else if (sizeof(npy_int32) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(npy_int32, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + npy_int32 val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (npy_int32) -1; + } + } else { + npy_int32 val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (npy_int32) -1; + val = __Pyx_PyInt_As_npy_int32(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to npy_int32"); + return (npy_int32) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to npy_int32"); + return (npy_int32) -1; +} + +/* CIntFromPy */ + static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { + const int neg_one = (int) -1, const_zero = (int) 0; + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* CIntToPy */ + static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { + const long neg_one = (long) -1, const_zero = (long) 0; + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* CIntFromPy */ + static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { + const long neg_one = (long) -1, const_zero = (long) 0; + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CheckBinaryVersion */ + static int __Pyx_check_binary_version(void) { + char ctversion[4], rtversion[4]; + PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); + PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion()); + if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) { + char message[200]; + PyOS_snprintf(message, sizeof(message), + "compiletime version %s of module '%.100s' " + "does not match runtime version %s", + ctversion, __Pyx_MODULE_NAME, rtversion); + return PyErr_WarnEx(NULL, message, 1); + } + return 0; +} + +/* ModuleImport */ + #ifndef __PYX_HAVE_RT_ImportModule +#define __PYX_HAVE_RT_ImportModule +static PyObject *__Pyx_ImportModule(const char *name) { + PyObject *py_name = 0; + PyObject *py_module = 0; + py_name = __Pyx_PyIdentifier_FromString(name); + if (!py_name) + goto bad; + py_module = PyImport_Import(py_name); + Py_DECREF(py_name); + return py_module; +bad: + Py_XDECREF(py_name); + return 0; +} +#endif + +/* TypeImport */ + #ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, + size_t size, int strict) +{ + PyObject *py_module = 0; + PyObject *result = 0; + PyObject *py_name = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + py_module = __Pyx_ImportModule(module_name); + if (!py_module) + goto bad; + py_name = __Pyx_PyIdentifier_FromString(class_name); + if (!py_name) + goto bad; + result = PyObject_GetAttr(py_module, py_name); + Py_DECREF(py_name); + py_name = 0; + Py_DECREF(py_module); + py_module = 0; + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if (!strict && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. Expected %zd, got %zd", + module_name, class_name, basicsize, size); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + else if ((size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s has the wrong size, try recompiling. Expected %zd, got %zd", + module_name, class_name, basicsize, size); + goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(py_module); + Py_XDECREF(result); + return NULL; +} +#endif + +/* InitStrings */ + static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { + while (t->p) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if CYTHON_COMPILING_IN_CPYTHON && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { +#if PY_VERSION_HEX < 0x03030000 + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +#else + if (__Pyx_PyUnicode_READY(o) == -1) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (PyUnicode_IS_ASCII(o)) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +#endif + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { + PyNumberMethods *m; + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (PyInt_Check(x) || PyLong_Check(x)) +#else + if (PyLong_Check(x)) +#endif + return __Pyx_NewRef(x); + m = Py_TYPE(x)->tp_as_number; +#if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = PyNumber_Int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = PyNumber_Long(x); + } +#else + if (m && m->nb_int) { + name = "int"; + res = PyNumber_Long(x); + } +#endif + if (res) { +#if PY_MAJOR_VERSION < 3 + if (!PyInt_Check(res) && !PyLong_Check(res)) { +#else + if (!PyLong_Check(res)) { +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + name, name, Py_TYPE(res)->tp_name); + Py_DECREF(res); + return NULL; + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(x); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ + diff --git a/easy_ViTPose/vit_utils/nms/gpu_nms.hpp b/easy_ViTPose/vit_utils/nms/gpu_nms.hpp new file mode 100644 index 0000000000000000000000000000000000000000..68b6d42cd88b59496b22a9e77919abe529b09014 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/gpu_nms.hpp @@ -0,0 +1,2 @@ +void _nms(int* keep_out, int* num_out, const float* boxes_host, int boxes_num, + int boxes_dim, float nms_overlap_thresh, int device_id); diff --git a/easy_ViTPose/vit_utils/nms/gpu_nms.pyx b/easy_ViTPose/vit_utils/nms/gpu_nms.pyx new file mode 100644 index 0000000000000000000000000000000000000000..e637d3ceff9b0614a046f8216c9ea51a30048375 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/gpu_nms.pyx @@ -0,0 +1,34 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft +# Licensed under the MIT License. +# Written by Bin Xiao (Bin.Xiao@microsoft.com) +# ------------------------------------------------------------------------------ + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np +cimport numpy as np + +assert sizeof(int) == sizeof(np.int32_t) + +cdef extern from "gpu_nms.hpp": + void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int) + +def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh, + np.int32_t device_id=0): + cdef int boxes_num = dets.shape[0] + cdef int boxes_dim = dets.shape[1] + cdef int num_out + cdef np.ndarray[np.int32_t, ndim=1] \ + keep = np.zeros(boxes_num, dtype=np.int32) + cdef np.ndarray[np.float32_t, ndim=1] \ + scores = dets[:, 4] + cdef np.ndarray[np.int32_t, ndim=1] \ + order = scores.argsort()[::-1].astype(np.int32) + cdef np.ndarray[np.float32_t, ndim=2] \ + sorted_dets = dets[order, :] + _nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id) + keep = keep[:num_out] + return list(order[keep]) diff --git a/easy_ViTPose/vit_utils/nms/nms.py b/easy_ViTPose/vit_utils/nms/nms.py new file mode 100644 index 0000000000000000000000000000000000000000..7f83e05eae638279ac3696548ff5a3d56795a1f1 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/nms.py @@ -0,0 +1,180 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft +# Licensed under the MIT License. +# Modified from py-faster-rcnn (https://github.com/rbgirshick/py-faster-rcnn) +# ------------------------------------------------------------------------------ + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from .cpu_nms import cpu_nms +from .gpu_nms import gpu_nms + + +def py_nms_wrapper(thresh): + def _nms(dets): + return nms(dets, thresh) + return _nms + + +def cpu_nms_wrapper(thresh): + def _nms(dets): + return cpu_nms(dets, thresh) + return _nms + + +def gpu_nms_wrapper(thresh, device_id): + def _nms(dets): + return gpu_nms(dets, thresh, device_id) + return _nms + + +def nms(dets, thresh): + """ + greedily select boxes with high confidence and overlap with current maximum <= thresh + rule out overlap >= thresh + :param dets: [[x1, y1, x2, y2 score]] + :param thresh: retain overlap < thresh + :return: indexes to keep + """ + if dets.shape[0] == 0: + return [] + + x1 = dets[:, 0] + y1 = dets[:, 1] + x2 = dets[:, 2] + y2 = dets[:, 3] + scores = dets[:, 4] + + areas = (x2 - x1 + 1) * (y2 - y1 + 1) + order = scores.argsort()[::-1] + + keep = [] + while order.size > 0: + i = order[0] + keep.append(i) + xx1 = np.maximum(x1[i], x1[order[1:]]) + yy1 = np.maximum(y1[i], y1[order[1:]]) + xx2 = np.minimum(x2[i], x2[order[1:]]) + yy2 = np.minimum(y2[i], y2[order[1:]]) + + w = np.maximum(0.0, xx2 - xx1 + 1) + h = np.maximum(0.0, yy2 - yy1 + 1) + inter = w * h + ovr = inter / (areas[i] + areas[order[1:]] - inter) + + inds = np.where(ovr <= thresh)[0] + order = order[inds + 1] + + return keep + + +def oks_iou(g, d, a_g, a_d, sigmas=None, in_vis_thre=None): + if not isinstance(sigmas, np.ndarray): + sigmas = np.array([.26, .25, .25, .35, .35, .79, .79, .72, .72, .62, .62, 1.07, 1.07, .87, .87, .89, .89]) / 10.0 + vars = (sigmas * 2) ** 2 + xg = g[0::3] + yg = g[1::3] + vg = g[2::3] + ious = np.zeros((d.shape[0])) + for n_d in range(0, d.shape[0]): + xd = d[n_d, 0::3] + yd = d[n_d, 1::3] + vd = d[n_d, 2::3] + dx = xd - xg + dy = yd - yg + e = (dx ** 2 + dy ** 2) / vars / ((a_g + a_d[n_d]) / 2 + np.spacing(1)) / 2 + if in_vis_thre is not None: + ind = list(vg > in_vis_thre) and list(vd > in_vis_thre) + e = e[ind] + ious[n_d] = np.sum(np.exp(-e)) / e.shape[0] if e.shape[0] != 0 else 0.0 + return ious + + +def oks_nms(kpts_db, thresh, sigmas=None, in_vis_thre=None): + """ + greedily select boxes with high confidence and overlap with current maximum <= thresh + rule out overlap >= thresh, overlap = oks + :param kpts_db + :param thresh: retain overlap < thresh + :return: indexes to keep + """ + if len(kpts_db) == 0: + return [] + + scores = np.array([kpts_db[i]['score'] for i in range(len(kpts_db))]) + kpts = np.array([kpts_db[i]['keypoints'].flatten() for i in range(len(kpts_db))]) + areas = np.array([kpts_db[i]['area'] for i in range(len(kpts_db))]) + + order = scores.argsort()[::-1] + + keep = [] + while order.size > 0: + i = order[0] + keep.append(i) + + oks_ovr = oks_iou(kpts[i], kpts[order[1:]], areas[i], areas[order[1:]], sigmas, in_vis_thre) + + inds = np.where(oks_ovr <= thresh)[0] + order = order[inds + 1] + + return keep + + +def rescore(overlap, scores, thresh, type='gaussian'): + assert overlap.shape[0] == scores.shape[0] + if type == 'linear': + inds = np.where(overlap >= thresh)[0] + scores[inds] = scores[inds] * (1 - overlap[inds]) + else: + scores = scores * np.exp(- overlap**2 / thresh) + + return scores + + +def soft_oks_nms(kpts_db, thresh, sigmas=None, in_vis_thre=None): + """ + greedily select boxes with high confidence and overlap with current maximum <= thresh + rule out overlap >= thresh, overlap = oks + :param kpts_db + :param thresh: retain overlap < thresh + :return: indexes to keep + """ + if len(kpts_db) == 0: + return [] + + scores = np.array([kpts_db[i]['score'] for i in range(len(kpts_db))]) + kpts = np.array([kpts_db[i]['keypoints'].flatten() for i in range(len(kpts_db))]) + areas = np.array([kpts_db[i]['area'] for i in range(len(kpts_db))]) + + order = scores.argsort()[::-1] + scores = scores[order] + + # max_dets = order.size + max_dets = 20 + keep = np.zeros(max_dets, dtype=np.intp) + keep_cnt = 0 + while order.size > 0 and keep_cnt < max_dets: + i = order[0] + + oks_ovr = oks_iou(kpts[i], kpts[order[1:]], areas[i], areas[order[1:]], sigmas, in_vis_thre) + + order = order[1:] + scores = rescore(oks_ovr, scores[1:], thresh) + + tmp = scores.argsort()[::-1] + order = order[tmp] + scores = scores[tmp] + + keep[keep_cnt] = i + keep_cnt += 1 + + keep = keep[:keep_cnt] + + return keep + # kpts_db = kpts_db[:keep_cnt] + + # return kpts_db diff --git a/easy_ViTPose/vit_utils/nms/nms_kernel.cu b/easy_ViTPose/vit_utils/nms/nms_kernel.cu new file mode 100644 index 0000000000000000000000000000000000000000..f6176c6de2274cbf9f3527a3b0220cd3f23f3ae6 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/nms_kernel.cu @@ -0,0 +1,143 @@ +// ------------------------------------------------------------------ +// Copyright (c) Microsoft +// Licensed under The MIT License +// Modified from MATLAB Faster R-CNN (https://github.com/shaoqingren/faster_rcnn) +// ------------------------------------------------------------------ + +#include "gpu_nms.hpp" +#include +#include + +#define CUDA_CHECK(condition) \ + /* Code block avoids redefinition of cudaError_t error */ \ + do { \ + cudaError_t error = condition; \ + if (error != cudaSuccess) { \ + std::cout << cudaGetErrorString(error) << std::endl; \ + } \ + } while (0) + +#define DIVUP(m,n) ((m) / (n) + ((m) % (n) > 0)) +int const threadsPerBlock = sizeof(unsigned long long) * 8; + +__device__ inline float devIoU(float const * const a, float const * const b) { + float left = max(a[0], b[0]), right = min(a[2], b[2]); + float top = max(a[1], b[1]), bottom = min(a[3], b[3]); + float width = max(right - left + 1, 0.f), height = max(bottom - top + 1, 0.f); + float interS = width * height; + float Sa = (a[2] - a[0] + 1) * (a[3] - a[1] + 1); + float Sb = (b[2] - b[0] + 1) * (b[3] - b[1] + 1); + return interS / (Sa + Sb - interS); +} + +__global__ void nms_kernel(const int n_boxes, const float nms_overlap_thresh, + const float *dev_boxes, unsigned long long *dev_mask) { + const int row_start = blockIdx.y; + const int col_start = blockIdx.x; + + // if (row_start > col_start) return; + + const int row_size = + min(n_boxes - row_start * threadsPerBlock, threadsPerBlock); + const int col_size = + min(n_boxes - col_start * threadsPerBlock, threadsPerBlock); + + __shared__ float block_boxes[threadsPerBlock * 5]; + if (threadIdx.x < col_size) { + block_boxes[threadIdx.x * 5 + 0] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 0]; + block_boxes[threadIdx.x * 5 + 1] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 1]; + block_boxes[threadIdx.x * 5 + 2] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 2]; + block_boxes[threadIdx.x * 5 + 3] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 3]; + block_boxes[threadIdx.x * 5 + 4] = + dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 4]; + } + __syncthreads(); + + if (threadIdx.x < row_size) { + const int cur_box_idx = threadsPerBlock * row_start + threadIdx.x; + const float *cur_box = dev_boxes + cur_box_idx * 5; + int i = 0; + unsigned long long t = 0; + int start = 0; + if (row_start == col_start) { + start = threadIdx.x + 1; + } + for (i = start; i < col_size; i++) { + if (devIoU(cur_box, block_boxes + i * 5) > nms_overlap_thresh) { + t |= 1ULL << i; + } + } + const int col_blocks = DIVUP(n_boxes, threadsPerBlock); + dev_mask[cur_box_idx * col_blocks + col_start] = t; + } +} + +void _set_device(int device_id) { + int current_device; + CUDA_CHECK(cudaGetDevice(¤t_device)); + if (current_device == device_id) { + return; + } + // The call to cudaSetDevice must come before any calls to Get, which + // may perform initialization using the GPU. + CUDA_CHECK(cudaSetDevice(device_id)); +} + +void _nms(int* keep_out, int* num_out, const float* boxes_host, int boxes_num, + int boxes_dim, float nms_overlap_thresh, int device_id) { + _set_device(device_id); + + float* boxes_dev = NULL; + unsigned long long* mask_dev = NULL; + + const int col_blocks = DIVUP(boxes_num, threadsPerBlock); + + CUDA_CHECK(cudaMalloc(&boxes_dev, + boxes_num * boxes_dim * sizeof(float))); + CUDA_CHECK(cudaMemcpy(boxes_dev, + boxes_host, + boxes_num * boxes_dim * sizeof(float), + cudaMemcpyHostToDevice)); + + CUDA_CHECK(cudaMalloc(&mask_dev, + boxes_num * col_blocks * sizeof(unsigned long long))); + + dim3 blocks(DIVUP(boxes_num, threadsPerBlock), + DIVUP(boxes_num, threadsPerBlock)); + dim3 threads(threadsPerBlock); + nms_kernel<<>>(boxes_num, + nms_overlap_thresh, + boxes_dev, + mask_dev); + + std::vector mask_host(boxes_num * col_blocks); + CUDA_CHECK(cudaMemcpy(&mask_host[0], + mask_dev, + sizeof(unsigned long long) * boxes_num * col_blocks, + cudaMemcpyDeviceToHost)); + + std::vector remv(col_blocks); + memset(&remv[0], 0, sizeof(unsigned long long) * col_blocks); + + int num_to_keep = 0; + for (int i = 0; i < boxes_num; i++) { + int nblock = i / threadsPerBlock; + int inblock = i % threadsPerBlock; + + if (!(remv[nblock] & (1ULL << inblock))) { + keep_out[num_to_keep++] = i; + unsigned long long *p = &mask_host[0] + i * col_blocks; + for (int j = nblock; j < col_blocks; j++) { + remv[j] |= p[j]; + } + } + } + *num_out = num_to_keep; + + CUDA_CHECK(cudaFree(boxes_dev)); + CUDA_CHECK(cudaFree(mask_dev)); +} diff --git a/easy_ViTPose/vit_utils/nms/nms_ori.py b/easy_ViTPose/vit_utils/nms/nms_ori.py new file mode 100644 index 0000000000000000000000000000000000000000..b881fe3dca72d1eceaca62877fc0541a73a7615e --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/nms_ori.py @@ -0,0 +1,180 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) Microsoft +# Licensed under the MIT License. +# Modified from py-faster-rcnn (https://github.com/rbgirshick/py-faster-rcnn) +# ------------------------------------------------------------------------------ + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from cpu_nms import cpu_nms +from gpu_nms import gpu_nms + + +def py_nms_wrapper(thresh): + def _nms(dets): + return nms(dets, thresh) + return _nms + + +def cpu_nms_wrapper(thresh): + def _nms(dets): + return cpu_nms(dets, thresh) + return _nms + + +def gpu_nms_wrapper(thresh, device_id): + def _nms(dets): + return gpu_nms(dets, thresh, device_id) + return _nms + + +def nms(dets, thresh): + """ + greedily select boxes with high confidence and overlap with current maximum <= thresh + rule out overlap >= thresh + :param dets: [[x1, y1, x2, y2 score]] + :param thresh: retain overlap < thresh + :return: indexes to keep + """ + if dets.shape[0] == 0: + return [] + + x1 = dets[:, 0] + y1 = dets[:, 1] + x2 = dets[:, 2] + y2 = dets[:, 3] + scores = dets[:, 4] + + areas = (x2 - x1 + 1) * (y2 - y1 + 1) + order = scores.argsort()[::-1] + + keep = [] + while order.size > 0: + i = order[0] + keep.append(i) + xx1 = np.maximum(x1[i], x1[order[1:]]) + yy1 = np.maximum(y1[i], y1[order[1:]]) + xx2 = np.minimum(x2[i], x2[order[1:]]) + yy2 = np.minimum(y2[i], y2[order[1:]]) + + w = np.maximum(0.0, xx2 - xx1 + 1) + h = np.maximum(0.0, yy2 - yy1 + 1) + inter = w * h + ovr = inter / (areas[i] + areas[order[1:]] - inter) + + inds = np.where(ovr <= thresh)[0] + order = order[inds + 1] + + return keep + + +def oks_iou(g, d, a_g, a_d, sigmas=None, in_vis_thre=None): + if not isinstance(sigmas, np.ndarray): + sigmas = np.array([.26, .25, .25, .35, .35, .79, .79, .72, .72, .62, .62, 1.07, 1.07, .87, .87, .89, .89]) / 10.0 + vars = (sigmas * 2) ** 2 + xg = g[0::3] + yg = g[1::3] + vg = g[2::3] + ious = np.zeros((d.shape[0])) + for n_d in range(0, d.shape[0]): + xd = d[n_d, 0::3] + yd = d[n_d, 1::3] + vd = d[n_d, 2::3] + dx = xd - xg + dy = yd - yg + e = (dx ** 2 + dy ** 2) / vars / ((a_g + a_d[n_d]) / 2 + np.spacing(1)) / 2 + if in_vis_thre is not None: + ind = list(vg > in_vis_thre) and list(vd > in_vis_thre) + e = e[ind] + ious[n_d] = np.sum(np.exp(-e)) / e.shape[0] if e.shape[0] != 0 else 0.0 + return ious + + +def oks_nms(kpts_db, thresh, sigmas=None, in_vis_thre=None): + """ + greedily select boxes with high confidence and overlap with current maximum <= thresh + rule out overlap >= thresh, overlap = oks + :param kpts_db + :param thresh: retain overlap < thresh + :return: indexes to keep + """ + if len(kpts_db) == 0: + return [] + + scores = np.array([kpts_db[i]['score'] for i in range(len(kpts_db))]) + kpts = np.array([kpts_db[i]['keypoints'].flatten() for i in range(len(kpts_db))]) + areas = np.array([kpts_db[i]['area'] for i in range(len(kpts_db))]) + + order = scores.argsort()[::-1] + + keep = [] + while order.size > 0: + i = order[0] + keep.append(i) + + oks_ovr = oks_iou(kpts[i], kpts[order[1:]], areas[i], areas[order[1:]], sigmas, in_vis_thre) + + inds = np.where(oks_ovr <= thresh)[0] + order = order[inds + 1] + + return keep + + +def rescore(overlap, scores, thresh, type='gaussian'): + assert overlap.shape[0] == scores.shape[0] + if type == 'linear': + inds = np.where(overlap >= thresh)[0] + scores[inds] = scores[inds] * (1 - overlap[inds]) + else: + scores = scores * np.exp(- overlap**2 / thresh) + + return scores + + +def soft_oks_nms(kpts_db, thresh, sigmas=None, in_vis_thre=None): + """ + greedily select boxes with high confidence and overlap with current maximum <= thresh + rule out overlap >= thresh, overlap = oks + :param kpts_db + :param thresh: retain overlap < thresh + :return: indexes to keep + """ + if len(kpts_db) == 0: + return [] + + scores = np.array([kpts_db[i]['score'] for i in range(len(kpts_db))]) + kpts = np.array([kpts_db[i]['keypoints'].flatten() for i in range(len(kpts_db))]) + areas = np.array([kpts_db[i]['area'] for i in range(len(kpts_db))]) + + order = scores.argsort()[::-1] + scores = scores[order] + + # max_dets = order.size + max_dets = 20 + keep = np.zeros(max_dets, dtype=np.intp) + keep_cnt = 0 + while order.size > 0 and keep_cnt < max_dets: + i = order[0] + + oks_ovr = oks_iou(kpts[i], kpts[order[1:]], areas[i], areas[order[1:]], sigmas, in_vis_thre) + + order = order[1:] + scores = rescore(oks_ovr, scores[1:], thresh) + + tmp = scores.argsort()[::-1] + order = order[tmp] + scores = scores[tmp] + + keep[keep_cnt] = i + keep_cnt += 1 + + keep = keep[:keep_cnt] + + return keep + # kpts_db = kpts_db[:keep_cnt] + + # return kpts_db diff --git a/easy_ViTPose/vit_utils/nms/setup_linux.py b/easy_ViTPose/vit_utils/nms/setup_linux.py new file mode 100644 index 0000000000000000000000000000000000000000..9120a93b92bbeee33c1f54dd4d288105f4575611 --- /dev/null +++ b/easy_ViTPose/vit_utils/nms/setup_linux.py @@ -0,0 +1,141 @@ +# -------------------------------------------------------- +# Pose.gluon +# Copyright (c) 2018-present Microsoft +# Licensed under The MIT License [see LICENSE for details] +# Modified from py-faster-rcnn (https://github.com/rbgirshick/py-faster-rcnn) +# -------------------------------------------------------- + +import os +from os.path import join as pjoin +from setuptools import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext +import numpy as np + + +def find_in_path(name, path): + "Find a file in a search path" + # Adapted fom + # http://code.activestate.com/recipes/52224-find-a-file-given-a-search-path/ + for dir in path.split(os.pathsep): + binpath = pjoin(dir, name) + if os.path.exists(binpath): + return os.path.abspath(binpath) + return None + + +def locate_cuda(): + """Locate the CUDA environment on the system + Returns a dict with keys 'home', 'nvcc', 'include', and 'lib64' + and values giving the absolute path to each directory. + Starts by looking for the CUDAHOME env variable. If not found, everything + is based on finding 'nvcc' in the PATH. + """ + + # first check if the CUDAHOME env variable is in use + if 'CUDAHOME' in os.environ: + home = os.environ['CUDAHOME'] + nvcc = pjoin(home, 'bin', 'nvcc') + else: + # otherwise, search the PATH for NVCC + default_path = pjoin(os.sep, 'usr', 'local', 'cuda', 'bin') + nvcc = find_in_path('nvcc', os.environ['PATH'] + os.pathsep + default_path) + if nvcc is None: + raise EnvironmentError('The nvcc binary could not be ' + 'located in your $PATH. Either add it to your path, or set $CUDAHOME') + home = os.path.dirname(os.path.dirname(nvcc)) + + cudaconfig = {'home':home, 'nvcc':nvcc, + 'include': pjoin(home, 'include'), + 'lib64': pjoin(home, 'lib64')} + for k, v in cudaconfig.items(): + if not os.path.exists(v): + raise EnvironmentError('The CUDA %s path could not be located in %s' % (k, v)) + + return cudaconfig +CUDA = locate_cuda() + + +# Obtain the numpy include directory. This logic works across numpy versions. +try: + numpy_include = np.get_include() +except AttributeError: + numpy_include = np.get_numpy_include() + + +def customize_compiler_for_nvcc(self): + """inject deep into distutils to customize how the dispatch + to gcc/nvcc works. + If you subclass UnixCCompiler, it's not trivial to get your subclass + injected in, and still have the right customizations (i.e. + distutils.sysconfig.customize_compiler) run on it. So instead of going + the OO route, I have this. Note, it's kindof like a wierd functional + subclassing going on.""" + + # tell the compiler it can processes .cu + self.src_extensions.append('.cu') + + # save references to the default compiler_so and _comple methods + default_compiler_so = self.compiler_so + super = self._compile + + # now redefine the _compile method. This gets executed for each + # object but distutils doesn't have the ability to change compilers + # based on source extension: we add it. + def _compile(obj, src, ext, cc_args, extra_postargs, pp_opts): + if os.path.splitext(src)[1] == '.cu': + # use the cuda for .cu files + self.set_executable('compiler_so', CUDA['nvcc']) + # use only a subset of the extra_postargs, which are 1-1 translated + # from the extra_compile_args in the Extension class + postargs = extra_postargs['nvcc'] + else: + postargs = extra_postargs['gcc'] + + super(obj, src, ext, cc_args, postargs, pp_opts) + # reset the default compiler_so, which we might have changed for cuda + self.compiler_so = default_compiler_so + + # inject our redefined _compile method into the class + self._compile = _compile + + +# run the customize_compiler +class custom_build_ext(build_ext): + def build_extensions(self): + customize_compiler_for_nvcc(self.compiler) + build_ext.build_extensions(self) + + +ext_modules = [ + Extension( + "cpu_nms", + ["cpu_nms.pyx"], + extra_compile_args={'gcc': ["-Wno-cpp", "-Wno-unused-function"]}, + include_dirs = [numpy_include] + ), + Extension('gpu_nms', + ['nms_kernel.cu', 'gpu_nms.pyx'], + library_dirs=[CUDA['lib64']], + libraries=['cudart'], + language='c++', + runtime_library_dirs=[CUDA['lib64']], + # this syntax is specific to this build system + # we're only going to use certain compiler args with nvcc and not with + # gcc the implementation of this trick is in customize_compiler() below + extra_compile_args={'gcc': ["-Wno-unused-function"], + 'nvcc': ['-arch=sm_35', + '--ptxas-options=-v', + '-c', + '--compiler-options', + "'-fPIC'"]}, + include_dirs = [numpy_include, CUDA['include']] + ), +] + +setup( + name='nms', + ext_modules=ext_modules, + # inject our custom trigger + cmdclass={'build_ext': custom_build_ext}, +) diff --git a/easy_ViTPose/vit_utils/post_processing/__init__.py b/easy_ViTPose/vit_utils/post_processing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1ee6858d953134a9b870b1a3635968729a4762ea --- /dev/null +++ b/easy_ViTPose/vit_utils/post_processing/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from .nms import oks_iou, oks_nms, soft_oks_nms +from .one_euro_filter import OneEuroFilter +from .post_transforms import (affine_transform, flip_back, fliplr_joints, + fliplr_regression, get_affine_transform, + get_warp_matrix, rotate_point, transform_preds, + warp_affine_joints) + +__all__ = [ + 'oks_nms', 'soft_oks_nms', 'affine_transform', 'rotate_point', 'flip_back', + 'fliplr_joints', 'fliplr_regression', 'transform_preds', + 'get_affine_transform', 'get_warp_matrix', 'warp_affine_joints', + 'OneEuroFilter', 'oks_iou' +] diff --git a/easy_ViTPose/vit_utils/post_processing/group.py b/easy_ViTPose/vit_utils/post_processing/group.py new file mode 100644 index 0000000000000000000000000000000000000000..e94f8ceacf64909041fad5b5613d98a0e79c99e9 --- /dev/null +++ b/easy_ViTPose/vit_utils/post_processing/group.py @@ -0,0 +1,410 @@ +# ------------------------------------------------------------------------------ +# Adapted from https://github.com/princeton-vl/pose-ae-train/ +# Original licence: Copyright (c) 2017, umich-vl, under BSD 3-Clause License. +# ------------------------------------------------------------------------------ + +import numpy as np +import torch +from munkres import Munkres + +from ..top_down_eval import post_dark_udp + + +def _py_max_match(scores): + """Apply munkres algorithm to get the best match. + + Args: + scores(np.ndarray): cost matrix. + + Returns: + np.ndarray: best match. + """ + m = Munkres() + tmp = m.compute(scores) + tmp = np.array(tmp).astype(int) + return tmp + + +def _match_by_tag(inp, params): + """Match joints by tags. Use Munkres algorithm to calculate the best match + for keypoints grouping. + + Note: + number of keypoints: K + max number of people in an image: M (M=30 by default) + dim of tags: L + If use flip testing, L=2; else L=1. + + Args: + inp(tuple): + tag_k (np.ndarray[KxMxL]): tag corresponding to the + top k values of feature map per keypoint. + loc_k (np.ndarray[KxMx2]): top k locations of the + feature maps for keypoint. + val_k (np.ndarray[KxM]): top k value of the + feature maps per keypoint. + params(Params): class Params(). + + Returns: + np.ndarray: result of pose groups. + """ + assert isinstance(params, _Params), 'params should be class _Params()' + + tag_k, loc_k, val_k = inp + + default_ = np.zeros((params.num_joints, 3 + tag_k.shape[2]), + dtype=np.float32) + + joint_dict = {} + tag_dict = {} + for i in range(params.num_joints): + idx = params.joint_order[i] + + tags = tag_k[idx] + joints = np.concatenate((loc_k[idx], val_k[idx, :, None], tags), 1) + mask = joints[:, 2] > params.detection_threshold + tags = tags[mask] + joints = joints[mask] + + if joints.shape[0] == 0: + continue + + if i == 0 or len(joint_dict) == 0: + for tag, joint in zip(tags, joints): + key = tag[0] + joint_dict.setdefault(key, np.copy(default_))[idx] = joint + tag_dict[key] = [tag] + else: + grouped_keys = list(joint_dict.keys())[:params.max_num_people] + grouped_tags = [np.mean(tag_dict[i], axis=0) for i in grouped_keys] + + if (params.ignore_too_much + and len(grouped_keys) == params.max_num_people): + continue + + diff = joints[:, None, 3:] - np.array(grouped_tags)[None, :, :] + diff_normed = np.linalg.norm(diff, ord=2, axis=2) + diff_saved = np.copy(diff_normed) + + if params.use_detection_val: + diff_normed = np.round(diff_normed) * 100 - joints[:, 2:3] + + num_added = diff.shape[0] + num_grouped = diff.shape[1] + + if num_added > num_grouped: + diff_normed = np.concatenate( + (diff_normed, + np.zeros((num_added, num_added - num_grouped), + dtype=np.float32) + 1e10), + axis=1) + + pairs = _py_max_match(diff_normed) + for row, col in pairs: + if (row < num_added and col < num_grouped + and diff_saved[row][col] < params.tag_threshold): + key = grouped_keys[col] + joint_dict[key][idx] = joints[row] + tag_dict[key].append(tags[row]) + else: + key = tags[row][0] + joint_dict.setdefault(key, np.copy(default_))[idx] = \ + joints[row] + tag_dict[key] = [tags[row]] + + results = np.array([joint_dict[i] for i in joint_dict]).astype(np.float32) + return results + + +class _Params: + """A class of parameter. + + Args: + cfg(Config): config. + """ + + def __init__(self, cfg): + self.num_joints = cfg['num_joints'] + self.max_num_people = cfg['max_num_people'] + + self.detection_threshold = cfg['detection_threshold'] + self.tag_threshold = cfg['tag_threshold'] + self.use_detection_val = cfg['use_detection_val'] + self.ignore_too_much = cfg['ignore_too_much'] + + if self.num_joints == 17: + self.joint_order = [ + i - 1 for i in + [1, 2, 3, 4, 5, 6, 7, 12, 13, 8, 9, 10, 11, 14, 15, 16, 17] + ] + else: + self.joint_order = list(np.arange(self.num_joints)) + + +class HeatmapParser: + """The heatmap parser for post processing.""" + + def __init__(self, cfg): + self.params = _Params(cfg) + self.tag_per_joint = cfg['tag_per_joint'] + self.pool = torch.nn.MaxPool2d(cfg['nms_kernel'], 1, + cfg['nms_padding']) + self.use_udp = cfg.get('use_udp', False) + self.score_per_joint = cfg.get('score_per_joint', False) + + def nms(self, heatmaps): + """Non-Maximum Suppression for heatmaps. + + Args: + heatmap(torch.Tensor): Heatmaps before nms. + + Returns: + torch.Tensor: Heatmaps after nms. + """ + + maxm = self.pool(heatmaps) + maxm = torch.eq(maxm, heatmaps).float() + heatmaps = heatmaps * maxm + + return heatmaps + + def match(self, tag_k, loc_k, val_k): + """Group keypoints to human poses in a batch. + + Args: + tag_k (np.ndarray[NxKxMxL]): tag corresponding to the + top k values of feature map per keypoint. + loc_k (np.ndarray[NxKxMx2]): top k locations of the + feature maps for keypoint. + val_k (np.ndarray[NxKxM]): top k value of the + feature maps per keypoint. + + Returns: + list + """ + + def _match(x): + return _match_by_tag(x, self.params) + + return list(map(_match, zip(tag_k, loc_k, val_k))) + + def top_k(self, heatmaps, tags): + """Find top_k values in an image. + + Note: + batch size: N + number of keypoints: K + heatmap height: H + heatmap width: W + max number of people: M + dim of tags: L + If use flip testing, L=2; else L=1. + + Args: + heatmaps (torch.Tensor[NxKxHxW]) + tags (torch.Tensor[NxKxHxWxL]) + + Returns: + dict: A dict containing top_k values. + + - tag_k (np.ndarray[NxKxMxL]): + tag corresponding to the top k values of + feature map per keypoint. + - loc_k (np.ndarray[NxKxMx2]): + top k location of feature map per keypoint. + - val_k (np.ndarray[NxKxM]): + top k value of feature map per keypoint. + """ + heatmaps = self.nms(heatmaps) + N, K, H, W = heatmaps.size() + heatmaps = heatmaps.view(N, K, -1) + val_k, ind = heatmaps.topk(self.params.max_num_people, dim=2) + + tags = tags.view(tags.size(0), tags.size(1), W * H, -1) + if not self.tag_per_joint: + tags = tags.expand(-1, self.params.num_joints, -1, -1) + + tag_k = torch.stack( + [torch.gather(tags[..., i], 2, ind) for i in range(tags.size(3))], + dim=3) + + x = ind % W + y = ind // W + + ind_k = torch.stack((x, y), dim=3) + + results = { + 'tag_k': tag_k.cpu().numpy(), + 'loc_k': ind_k.cpu().numpy(), + 'val_k': val_k.cpu().numpy() + } + + return results + + @staticmethod + def adjust(results, heatmaps): + """Adjust the coordinates for better accuracy. + + Note: + batch size: N + number of keypoints: K + heatmap height: H + heatmap width: W + + Args: + results (list(np.ndarray)): Keypoint predictions. + heatmaps (torch.Tensor[NxKxHxW]): Heatmaps. + """ + _, _, H, W = heatmaps.shape + for batch_id, people in enumerate(results): + for people_id, people_i in enumerate(people): + for joint_id, joint in enumerate(people_i): + if joint[2] > 0: + x, y = joint[0:2] + xx, yy = int(x), int(y) + tmp = heatmaps[batch_id][joint_id] + if tmp[min(H - 1, yy + 1), xx] > tmp[max(0, yy - 1), + xx]: + y += 0.25 + else: + y -= 0.25 + + if tmp[yy, min(W - 1, xx + 1)] > tmp[yy, + max(0, xx - 1)]: + x += 0.25 + else: + x -= 0.25 + results[batch_id][people_id, joint_id, + 0:2] = (x + 0.5, y + 0.5) + return results + + @staticmethod + def refine(heatmap, tag, keypoints, use_udp=False): + """Given initial keypoint predictions, we identify missing joints. + + Note: + number of keypoints: K + heatmap height: H + heatmap width: W + dim of tags: L + If use flip testing, L=2; else L=1. + + Args: + heatmap: np.ndarray(K, H, W). + tag: np.ndarray(K, H, W) | np.ndarray(K, H, W, L) + keypoints: np.ndarray of size (K, 3 + L) + last dim is (x, y, score, tag). + use_udp: bool-unbiased data processing + + Returns: + np.ndarray: The refined keypoints. + """ + + K, H, W = heatmap.shape + if len(tag.shape) == 3: + tag = tag[..., None] + + tags = [] + for i in range(K): + if keypoints[i, 2] > 0: + # save tag value of detected keypoint + x, y = keypoints[i][:2].astype(int) + x = np.clip(x, 0, W - 1) + y = np.clip(y, 0, H - 1) + tags.append(tag[i, y, x]) + + # mean tag of current detected people + prev_tag = np.mean(tags, axis=0) + results = [] + + for _heatmap, _tag in zip(heatmap, tag): + # distance of all tag values with mean tag of + # current detected people + distance_tag = (((_tag - + prev_tag[None, None, :])**2).sum(axis=2)**0.5) + norm_heatmap = _heatmap - np.round(distance_tag) + + # find maximum position + y, x = np.unravel_index(np.argmax(norm_heatmap), _heatmap.shape) + xx = x.copy() + yy = y.copy() + # detection score at maximum position + val = _heatmap[y, x] + if not use_udp: + # offset by 0.5 + x += 0.5 + y += 0.5 + + # add a quarter offset + if _heatmap[yy, min(W - 1, xx + 1)] > _heatmap[yy, max(0, xx - 1)]: + x += 0.25 + else: + x -= 0.25 + + if _heatmap[min(H - 1, yy + 1), xx] > _heatmap[max(0, yy - 1), xx]: + y += 0.25 + else: + y -= 0.25 + + results.append((x, y, val)) + results = np.array(results) + + if results is not None: + for i in range(K): + # add keypoint if it is not detected + if results[i, 2] > 0 and keypoints[i, 2] == 0: + keypoints[i, :3] = results[i, :3] + + return keypoints + + def parse(self, heatmaps, tags, adjust=True, refine=True): + """Group keypoints into poses given heatmap and tag. + + Note: + batch size: N + number of keypoints: K + heatmap height: H + heatmap width: W + dim of tags: L + If use flip testing, L=2; else L=1. + + Args: + heatmaps (torch.Tensor[NxKxHxW]): model output heatmaps. + tags (torch.Tensor[NxKxHxWxL]): model output tagmaps. + + Returns: + tuple: A tuple containing keypoint grouping results. + + - results (list(np.ndarray)): Pose results. + - scores (list/list(np.ndarray)): Score of people. + """ + results = self.match(**self.top_k(heatmaps, tags)) + + if adjust: + if self.use_udp: + for i in range(len(results)): + if results[i].shape[0] > 0: + results[i][..., :2] = post_dark_udp( + results[i][..., :2].copy(), heatmaps[i:i + 1, :]) + else: + results = self.adjust(results, heatmaps) + + if self.score_per_joint: + scores = [i[:, 2] for i in results[0]] + else: + scores = [i[:, 2].mean() for i in results[0]] + + if refine: + results = results[0] + # for every detected person + for i in range(len(results)): + heatmap_numpy = heatmaps[0].cpu().numpy() + tag_numpy = tags[0].cpu().numpy() + if not self.tag_per_joint: + tag_numpy = np.tile(tag_numpy, + (self.params.num_joints, 1, 1, 1)) + results[i] = self.refine( + heatmap_numpy, tag_numpy, results[i], use_udp=self.use_udp) + results = [results] + + return results, scores diff --git a/easy_ViTPose/vit_utils/post_processing/nms.py b/easy_ViTPose/vit_utils/post_processing/nms.py new file mode 100644 index 0000000000000000000000000000000000000000..86a0ab35e0e26d27bb0bb55071018ffc5ac9af1d --- /dev/null +++ b/easy_ViTPose/vit_utils/post_processing/nms.py @@ -0,0 +1,207 @@ +# ------------------------------------------------------------------------------ +# Adapted from https://github.com/leoxiaobin/deep-high-resolution-net.pytorch +# Original licence: Copyright (c) Microsoft, under the MIT License. +# ------------------------------------------------------------------------------ + +import numpy as np + + +def nms(dets, thr): + """Greedily select boxes with high confidence and overlap <= thr. + + Args: + dets: [[x1, y1, x2, y2, score]]. + thr: Retain overlap < thr. + + Returns: + list: Indexes to keep. + """ + if len(dets) == 0: + return [] + + x1 = dets[:, 0] + y1 = dets[:, 1] + x2 = dets[:, 2] + y2 = dets[:, 3] + scores = dets[:, 4] + + areas = (x2 - x1 + 1) * (y2 - y1 + 1) + order = scores.argsort()[::-1] + + keep = [] + while len(order) > 0: + i = order[0] + keep.append(i) + xx1 = np.maximum(x1[i], x1[order[1:]]) + yy1 = np.maximum(y1[i], y1[order[1:]]) + xx2 = np.minimum(x2[i], x2[order[1:]]) + yy2 = np.minimum(y2[i], y2[order[1:]]) + + w = np.maximum(0.0, xx2 - xx1 + 1) + h = np.maximum(0.0, yy2 - yy1 + 1) + inter = w * h + ovr = inter / (areas[i] + areas[order[1:]] - inter) + + inds = np.where(ovr <= thr)[0] + order = order[inds + 1] + + return keep + + +def oks_iou(g, d, a_g, a_d, sigmas=None, vis_thr=None): + """Calculate oks ious. + + Args: + g: Ground truth keypoints. + d: Detected keypoints. + a_g: Area of the ground truth object. + a_d: Area of the detected object. + sigmas: standard deviation of keypoint labelling. + vis_thr: threshold of the keypoint visibility. + + Returns: + list: The oks ious. + """ + if sigmas is None: + sigmas = np.array([ + .26, .25, .25, .35, .35, .79, .79, .72, .72, .62, .62, 1.07, 1.07, + .87, .87, .89, .89 + ]) / 10.0 + vars = (sigmas * 2)**2 + xg = g[0::3] + yg = g[1::3] + vg = g[2::3] + ious = np.zeros(len(d), dtype=np.float32) + for n_d in range(0, len(d)): + xd = d[n_d, 0::3] + yd = d[n_d, 1::3] + vd = d[n_d, 2::3] + dx = xd - xg + dy = yd - yg + e = (dx**2 + dy**2) / vars / ((a_g + a_d[n_d]) / 2 + np.spacing(1)) / 2 + if vis_thr is not None: + ind = list(vg > vis_thr) and list(vd > vis_thr) + e = e[ind] + ious[n_d] = np.sum(np.exp(-e)) / len(e) if len(e) != 0 else 0.0 + return ious + + +def oks_nms(kpts_db, thr, sigmas=None, vis_thr=None, score_per_joint=False): + """OKS NMS implementations. + + Args: + kpts_db: keypoints. + thr: Retain overlap < thr. + sigmas: standard deviation of keypoint labelling. + vis_thr: threshold of the keypoint visibility. + score_per_joint: the input scores (in kpts_db) are per joint scores + + Returns: + np.ndarray: indexes to keep. + """ + if len(kpts_db) == 0: + return [] + + if score_per_joint: + scores = np.array([k['score'].mean() for k in kpts_db]) + else: + scores = np.array([k['score'] for k in kpts_db]) + + kpts = np.array([k['keypoints'].flatten() for k in kpts_db]) + areas = np.array([k['area'] for k in kpts_db]) + + order = scores.argsort()[::-1] + + keep = [] + while len(order) > 0: + i = order[0] + keep.append(i) + + oks_ovr = oks_iou(kpts[i], kpts[order[1:]], areas[i], areas[order[1:]], + sigmas, vis_thr) + + inds = np.where(oks_ovr <= thr)[0] + order = order[inds + 1] + + keep = np.array(keep) + + return keep + + +def _rescore(overlap, scores, thr, type='gaussian'): + """Rescoring mechanism gaussian or linear. + + Args: + overlap: calculated ious + scores: target scores. + thr: retain oks overlap < thr. + type: 'gaussian' or 'linear' + + Returns: + np.ndarray: indexes to keep + """ + assert len(overlap) == len(scores) + assert type in ['gaussian', 'linear'] + + if type == 'linear': + inds = np.where(overlap >= thr)[0] + scores[inds] = scores[inds] * (1 - overlap[inds]) + else: + scores = scores * np.exp(-overlap**2 / thr) + + return scores + + +def soft_oks_nms(kpts_db, + thr, + max_dets=20, + sigmas=None, + vis_thr=None, + score_per_joint=False): + """Soft OKS NMS implementations. + + Args: + kpts_db + thr: retain oks overlap < thr. + max_dets: max number of detections to keep. + sigmas: Keypoint labelling uncertainty. + score_per_joint: the input scores (in kpts_db) are per joint scores + + Returns: + np.ndarray: indexes to keep. + """ + if len(kpts_db) == 0: + return [] + + if score_per_joint: + scores = np.array([k['score'].mean() for k in kpts_db]) + else: + scores = np.array([k['score'] for k in kpts_db]) + + kpts = np.array([k['keypoints'].flatten() for k in kpts_db]) + areas = np.array([k['area'] for k in kpts_db]) + + order = scores.argsort()[::-1] + scores = scores[order] + + keep = np.zeros(max_dets, dtype=np.intp) + keep_cnt = 0 + while len(order) > 0 and keep_cnt < max_dets: + i = order[0] + + oks_ovr = oks_iou(kpts[i], kpts[order[1:]], areas[i], areas[order[1:]], + sigmas, vis_thr) + + order = order[1:] + scores = _rescore(oks_ovr, scores[1:], thr) + + tmp = scores.argsort()[::-1] + order = order[tmp] + scores = scores[tmp] + + keep[keep_cnt] = i + keep_cnt += 1 + + keep = keep[:keep_cnt] + + return keep diff --git a/easy_ViTPose/vit_utils/post_processing/one_euro_filter.py b/easy_ViTPose/vit_utils/post_processing/one_euro_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..01ffa5fda9b1669e3611f14643ed731669b3b421 --- /dev/null +++ b/easy_ViTPose/vit_utils/post_processing/one_euro_filter.py @@ -0,0 +1,102 @@ +# ------------------------------------------------------------------------------ +# Adapted from https://github.com/HoBeom/OneEuroFilter-Numpy +# Original licence: Copyright (c) HoBeom Jeon, under the MIT License. +# ------------------------------------------------------------------------------ +from time import time + +import numpy as np + + +def smoothing_factor(t_e, cutoff): + r = 2 * np.pi * cutoff * t_e + return r / (r + 1) + + +def exponential_smoothing(a, x, x_prev): + return a * x + (1 - a) * x_prev + + +class OneEuroFilter: + + def __init__(self, + x0, + dx0=0.0, + min_cutoff=1.7, + beta=0.3, + d_cutoff=30.0, + fps=None): + """One Euro Filter for keypoints smoothing. + + Args: + x0 (np.ndarray[K, 2]): Initialize keypoints value + dx0 (float): 0.0 + min_cutoff (float): parameter for one euro filter + beta (float): parameter for one euro filter + d_cutoff (float): Input data FPS + fps (float): Video FPS for video inference + """ + + # The parameters. + self.data_shape = x0.shape + self.min_cutoff = np.full(x0.shape, min_cutoff) + self.beta = np.full(x0.shape, beta) + self.d_cutoff = np.full(x0.shape, d_cutoff) + # Previous values. + self.x_prev = x0.astype(np.float32) + self.dx_prev = np.full(x0.shape, dx0) + self.mask_prev = np.ma.masked_where(x0 <= 0, x0) + self.realtime = True + if fps is None: + # Using in realtime inference + self.t_e = None + self.skip_frame_factor = d_cutoff + else: + # fps using video inference + self.realtime = False + self.d_cutoff = np.full(x0.shape, float(fps)) + self.t_prev = time() + + def __call__(self, x, t_e=1.0): + """Compute the filtered signal. + + Hyper-parameters (cutoff, beta) are from `VNect + `__ . + + Realtime Camera fps (d_cutoff) default 30.0 + + Args: + x (np.ndarray[K, 2]): keypoints results in frame + t_e (Optional): video skip frame count for posetrack + evaluation + """ + assert x.shape == self.data_shape + + t = 0 + if self.realtime: + t = time() + t_e = (t - self.t_prev) * self.skip_frame_factor + t_e = np.full(x.shape, t_e) + + # missing keypoints mask + mask = np.ma.masked_where(x <= 0, x) + + # The filtered derivative of the signal. + a_d = smoothing_factor(t_e, self.d_cutoff) + dx = (x - self.x_prev) / t_e + dx_hat = exponential_smoothing(a_d, dx, self.dx_prev) + + # The filtered signal. + cutoff = self.min_cutoff + self.beta * np.abs(dx_hat) + a = smoothing_factor(t_e, cutoff) + x_hat = exponential_smoothing(a, x, self.x_prev) + + # missing keypoints remove + np.copyto(x_hat, -10, where=mask.mask) + + # Memorize the previous values. + self.x_prev = x_hat + self.dx_prev = dx_hat + self.t_prev = t + self.mask_prev = mask + + return x_hat diff --git a/easy_ViTPose/vit_utils/post_processing/post_transforms.py b/easy_ViTPose/vit_utils/post_processing/post_transforms.py new file mode 100644 index 0000000000000000000000000000000000000000..c20476195d5852df34e4be4955d65e59d913fa00 --- /dev/null +++ b/easy_ViTPose/vit_utils/post_processing/post_transforms.py @@ -0,0 +1,366 @@ +# ------------------------------------------------------------------------------ +# Adapted from https://github.com/leoxiaobin/deep-high-resolution-net.pytorch +# Original licence: Copyright (c) Microsoft, under the MIT License. +# ------------------------------------------------------------------------------ + +import math + +import cv2 +import numpy as np +import torch + + +def fliplr_joints(joints_3d, joints_3d_visible, img_width, flip_pairs): + """Flip human joints horizontally. + + Note: + - num_keypoints: K + + Args: + joints_3d (np.ndarray([K, 3])): Coordinates of keypoints. + joints_3d_visible (np.ndarray([K, 1])): Visibility of keypoints. + img_width (int): Image width. + flip_pairs (list[tuple]): Pairs of keypoints which are mirrored + (for example, left ear and right ear). + + Returns: + tuple: Flipped human joints. + + - joints_3d_flipped (np.ndarray([K, 3])): Flipped joints. + - joints_3d_visible_flipped (np.ndarray([K, 1])): Joint visibility. + """ + + assert len(joints_3d) == len(joints_3d_visible) + assert img_width > 0 + + joints_3d_flipped = joints_3d.copy() + joints_3d_visible_flipped = joints_3d_visible.copy() + + # Swap left-right parts + for left, right in flip_pairs: + joints_3d_flipped[left, :] = joints_3d[right, :] + joints_3d_flipped[right, :] = joints_3d[left, :] + + joints_3d_visible_flipped[left, :] = joints_3d_visible[right, :] + joints_3d_visible_flipped[right, :] = joints_3d_visible[left, :] + + # Flip horizontally + joints_3d_flipped[:, 0] = img_width - 1 - joints_3d_flipped[:, 0] + joints_3d_flipped = joints_3d_flipped * joints_3d_visible_flipped + + return joints_3d_flipped, joints_3d_visible_flipped + + +def fliplr_regression(regression, + flip_pairs, + center_mode='static', + center_x=0.5, + center_index=0): + """Flip human joints horizontally. + + Note: + - batch_size: N + - num_keypoint: K + + Args: + regression (np.ndarray([..., K, C])): Coordinates of keypoints, where K + is the joint number and C is the dimension. Example shapes are: + + - [N, K, C]: a batch of keypoints where N is the batch size. + - [N, T, K, C]: a batch of pose sequences, where T is the frame + number. + flip_pairs (list[tuple()]): Pairs of keypoints which are mirrored + (for example, left ear -- right ear). + center_mode (str): The mode to set the center location on the x-axis + to flip around. Options are: + + - static: use a static x value (see center_x also) + - root: use a root joint (see center_index also) + center_x (float): Set the x-axis location of the flip center. Only used + when center_mode=static. + center_index (int): Set the index of the root joint, whose x location + will be used as the flip center. Only used when center_mode=root. + + Returns: + np.ndarray([..., K, C]): Flipped joints. + """ + assert regression.ndim >= 2, f'Invalid pose shape {regression.shape}' + + allowed_center_mode = {'static', 'root'} + assert center_mode in allowed_center_mode, 'Get invalid center_mode ' \ + f'{center_mode}, allowed choices are {allowed_center_mode}' + + if center_mode == 'static': + x_c = center_x + elif center_mode == 'root': + assert regression.shape[-2] > center_index + x_c = regression[..., center_index:center_index + 1, 0] + + regression_flipped = regression.copy() + # Swap left-right parts + for left, right in flip_pairs: + regression_flipped[..., left, :] = regression[..., right, :] + regression_flipped[..., right, :] = regression[..., left, :] + + # Flip horizontally + regression_flipped[..., 0] = x_c * 2 - regression_flipped[..., 0] + return regression_flipped + + +def flip_back(output_flipped, flip_pairs, target_type='GaussianHeatmap'): + """Flip the flipped heatmaps back to the original form. + + Note: + - batch_size: N + - num_keypoints: K + - heatmap height: H + - heatmap width: W + + Args: + output_flipped (np.ndarray[N, K, H, W]): The output heatmaps obtained + from the flipped images. + flip_pairs (list[tuple()): Pairs of keypoints which are mirrored + (for example, left ear -- right ear). + target_type (str): GaussianHeatmap or CombinedTarget + + Returns: + np.ndarray: heatmaps that flipped back to the original image + """ + assert output_flipped.ndim == 4, \ + 'output_flipped should be [batch_size, num_keypoints, height, width]' + shape_ori = output_flipped.shape + channels = 1 + if target_type.lower() == 'CombinedTarget'.lower(): + channels = 3 + output_flipped[:, 1::3, ...] = -output_flipped[:, 1::3, ...] + output_flipped = output_flipped.reshape(shape_ori[0], -1, channels, + shape_ori[2], shape_ori[3]) + output_flipped_back = output_flipped.copy() + + # Swap left-right parts + for left, right in flip_pairs: + output_flipped_back[:, left, ...] = output_flipped[:, right, ...] + output_flipped_back[:, right, ...] = output_flipped[:, left, ...] + output_flipped_back = output_flipped_back.reshape(shape_ori) + # Flip horizontally + output_flipped_back = output_flipped_back[..., ::-1] + return output_flipped_back + + +def transform_preds(coords, center, scale, output_size, use_udp=False): + """Get final keypoint predictions from heatmaps and apply scaling and + translation to map them back to the image. + + Note: + num_keypoints: K + + Args: + coords (np.ndarray[K, ndims]): + + * If ndims=2, corrds are predicted keypoint location. + * If ndims=4, corrds are composed of (x, y, scores, tags) + * If ndims=5, corrds are composed of (x, y, scores, tags, + flipped_tags) + + center (np.ndarray[2, ]): Center of the bounding box (x, y). + scale (np.ndarray[2, ]): Scale of the bounding box + wrt [width, height]. + output_size (np.ndarray[2, ] | list(2,)): Size of the + destination heatmaps. + use_udp (bool): Use unbiased data processing + + Returns: + np.ndarray: Predicted coordinates in the images. + """ + assert coords.shape[1] in (2, 4, 5) + assert len(center) == 2 + assert len(scale) == 2 + assert len(output_size) == 2 + + # Recover the scale which is normalized by a factor of 200. + # scale = scale * 200.0 + + if use_udp: + scale_x = scale[0] / (output_size[0] - 1.0) + scale_y = scale[1] / (output_size[1] - 1.0) + else: + scale_x = scale[0] / output_size[0] + scale_y = scale[1] / output_size[1] + + target_coords = np.ones_like(coords) + target_coords[:, 0] = coords[:, 0] * scale_x + center[0] - scale[0] * 0.5 + target_coords[:, 1] = coords[:, 1] * scale_y + center[1] - scale[1] * 0.5 + + return target_coords + + +def get_affine_transform(center, + scale, + rot, + output_size, + shift=(0., 0.), + inv=False): + """Get the affine transform matrix, given the center/scale/rot/output_size. + + Args: + center (np.ndarray[2, ]): Center of the bounding box (x, y). + scale (np.ndarray[2, ]): Scale of the bounding box + wrt [width, height]. + rot (float): Rotation angle (degree). + output_size (np.ndarray[2, ] | list(2,)): Size of the + destination heatmaps. + shift (0-100%): Shift translation ratio wrt the width/height. + Default (0., 0.). + inv (bool): Option to inverse the affine transform direction. + (inv=False: src->dst or inv=True: dst->src) + + Returns: + np.ndarray: The transform matrix. + """ + assert len(center) == 2 + assert len(scale) == 2 + assert len(output_size) == 2 + assert len(shift) == 2 + + # pixel_std is 200. + scale_tmp = scale * 200.0 + + shift = np.array(shift) + src_w = scale_tmp[0] + dst_w = output_size[0] + dst_h = output_size[1] + + rot_rad = np.pi * rot / 180 + src_dir = rotate_point([0., src_w * -0.5], rot_rad) + dst_dir = np.array([0., dst_w * -0.5]) + + src = np.zeros((3, 2), dtype=np.float32) + src[0, :] = center + scale_tmp * shift + src[1, :] = center + src_dir + scale_tmp * shift + src[2, :] = _get_3rd_point(src[0, :], src[1, :]) + + dst = np.zeros((3, 2), dtype=np.float32) + dst[0, :] = [dst_w * 0.5, dst_h * 0.5] + dst[1, :] = np.array([dst_w * 0.5, dst_h * 0.5]) + dst_dir + dst[2, :] = _get_3rd_point(dst[0, :], dst[1, :]) + + if inv: + trans = cv2.getAffineTransform(np.float32(dst), np.float32(src)) + else: + trans = cv2.getAffineTransform(np.float32(src), np.float32(dst)) + + return trans + + +def affine_transform(pt, trans_mat): + """Apply an affine transformation to the points. + + Args: + pt (np.ndarray): a 2 dimensional point to be transformed + trans_mat (np.ndarray): 2x3 matrix of an affine transform + + Returns: + np.ndarray: Transformed points. + """ + assert len(pt) == 2 + new_pt = np.array(trans_mat) @ np.array([pt[0], pt[1], 1.]) + + return new_pt + + +def _get_3rd_point(a, b): + """To calculate the affine matrix, three pairs of points are required. This + function is used to get the 3rd point, given 2D points a & b. + + The 3rd point is defined by rotating vector `a - b` by 90 degrees + anticlockwise, using b as the rotation center. + + Args: + a (np.ndarray): point(x,y) + b (np.ndarray): point(x,y) + + Returns: + np.ndarray: The 3rd point. + """ + assert len(a) == 2 + assert len(b) == 2 + direction = a - b + third_pt = b + np.array([-direction[1], direction[0]], dtype=np.float32) + + return third_pt + + +def rotate_point(pt, angle_rad): + """Rotate a point by an angle. + + Args: + pt (list[float]): 2 dimensional point to be rotated + angle_rad (float): rotation angle by radian + + Returns: + list[float]: Rotated point. + """ + assert len(pt) == 2 + sn, cs = np.sin(angle_rad), np.cos(angle_rad) + new_x = pt[0] * cs - pt[1] * sn + new_y = pt[0] * sn + pt[1] * cs + rotated_pt = [new_x, new_y] + + return rotated_pt + + +def get_warp_matrix(theta, size_input, size_dst, size_target): + """Calculate the transformation matrix under the constraint of unbiased. + Paper ref: Huang et al. The Devil is in the Details: Delving into Unbiased + Data Processing for Human Pose Estimation (CVPR 2020). + + Args: + theta (float): Rotation angle in degrees. + size_input (np.ndarray): Size of input image [w, h]. + size_dst (np.ndarray): Size of output image [w, h]. + size_target (np.ndarray): Size of ROI in input plane [w, h]. + + Returns: + np.ndarray: A matrix for transformation. + """ + theta = np.deg2rad(theta) + matrix = np.zeros((2, 3), dtype=np.float32) + scale_x = size_dst[0] / size_target[0] + scale_y = size_dst[1] / size_target[1] + matrix[0, 0] = math.cos(theta) * scale_x + matrix[0, 1] = -math.sin(theta) * scale_x + matrix[0, 2] = scale_x * (-0.5 * size_input[0] * math.cos(theta) + + 0.5 * size_input[1] * math.sin(theta) + + 0.5 * size_target[0]) + matrix[1, 0] = math.sin(theta) * scale_y + matrix[1, 1] = math.cos(theta) * scale_y + matrix[1, 2] = scale_y * (-0.5 * size_input[0] * math.sin(theta) - + 0.5 * size_input[1] * math.cos(theta) + + 0.5 * size_target[1]) + return matrix + + +def warp_affine_joints(joints, mat): + """Apply affine transformation defined by the transform matrix on the + joints. + + Args: + joints (np.ndarray[..., 2]): Origin coordinate of joints. + mat (np.ndarray[3, 2]): The affine matrix. + + Returns: + np.ndarray[..., 2]: Result coordinate of joints. + """ + joints = np.array(joints) + shape = joints.shape + joints = joints.reshape(-1, 2) + return np.dot( + np.concatenate((joints, joints[:, 0:1] * 0 + 1), axis=1), + mat.T).reshape(shape) + + +def affine_transform_torch(pts, t): + npts = pts.shape[0] + pts_homo = torch.cat([pts, torch.ones(npts, 1, device=pts.device)], dim=1) + out = torch.mm(t, torch.t(pts_homo)) + return torch.t(out[:2, :]) diff --git a/easy_ViTPose/vit_utils/top_down_eval.py b/easy_ViTPose/vit_utils/top_down_eval.py new file mode 100644 index 0000000000000000000000000000000000000000..8a1e0f866b88efb2ea5807b847849e94d8891ec1 --- /dev/null +++ b/easy_ViTPose/vit_utils/top_down_eval.py @@ -0,0 +1,703 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import warnings + +import cv2 +import numpy as np + +from .post_processing import transform_preds + +# def heatmap2coords(heatmaps: np.ndarray, original_resolution: tuple[int, int]=(256, 192)) -> np.ndarray: +# __, __, heatmap_h, heatmap_w = heatmaps.shape +# output = [] +# for heatmap in heatmaps: +# keypoint_coords = [] +# for joint in heatmap: +# keypoint_coord = np.unravel_index(np.argmax(joint), (heatmap_h, heatmap_w)) +# """ +# - 0: coord_y / (height//4) * bbox_height + bb_y1 +# - 1: coord_x / (width//4) * bbox_width + bb_x1 +# - 2: confidences +# """ +# coord_y = keypoint_coord[0] / heatmap_h*original_resolution[0] +# coord_x = keypoint_coord[1] / heatmap_w*original_resolution[1] +# prob = joint[keypoint_coord] +# keypoint_coords.append([coord_y, coord_x, prob]) +# output.append(keypoint_coords) + +# return np.array(output).astype(float) + +def _calc_distances(preds, targets, mask, normalize): + """Calculate the normalized distances between preds and target. + + Note: + batch_size: N + num_keypoints: K + dimension of keypoints: D (normally, D=2 or D=3) + + Args: + preds (np.ndarray[N, K, D]): Predicted keypoint location. + targets (np.ndarray[N, K, D]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + normalize (np.ndarray[N, D]): Typical value is heatmap_size + + Returns: + np.ndarray[K, N]: The normalized distances. \ + If target keypoints are missing, the distance is -1. + """ + N, K, _ = preds.shape + # set mask=0 when normalize==0 + _mask = mask.copy() + _mask[np.where((normalize == 0).sum(1))[0], :] = False + distances = np.full((N, K), -1, dtype=np.float32) + # handle invalid values + normalize[np.where(normalize <= 0)] = 1e6 + distances[_mask] = np.linalg.norm( + ((preds - targets) / normalize[:, None, :])[_mask], axis=-1) + return distances.T + + +def _distance_acc(distances, thr=0.5): + """Return the percentage below the distance threshold, while ignoring + distances values with -1. + + Note: + batch_size: N + Args: + distances (np.ndarray[N, ]): The normalized distances. + thr (float): Threshold of the distances. + + Returns: + float: Percentage of distances below the threshold. \ + If all target keypoints are missing, return -1. + """ + distance_valid = distances != -1 + num_distance_valid = distance_valid.sum() + if num_distance_valid > 0: + return (distances[distance_valid] < thr).sum() / num_distance_valid + return -1 + + +def _get_max_preds(heatmaps): + """Get keypoint predictions from score maps. + + Note: + batch_size: N + num_keypoints: K + heatmap height: H + heatmap width: W + + Args: + heatmaps (np.ndarray[N, K, H, W]): model predicted heatmaps. + + Returns: + tuple: A tuple containing aggregated results. + + - preds (np.ndarray[N, K, 2]): Predicted keypoint location. + - maxvals (np.ndarray[N, K, 1]): Scores (confidence) of the keypoints. + """ + assert isinstance(heatmaps, + np.ndarray), ('heatmaps should be numpy.ndarray') + assert heatmaps.ndim == 4, 'batch_images should be 4-ndim' + + N, K, _, W = heatmaps.shape + heatmaps_reshaped = heatmaps.reshape((N, K, -1)) + idx = np.argmax(heatmaps_reshaped, 2).reshape((N, K, 1)) + maxvals = np.amax(heatmaps_reshaped, 2).reshape((N, K, 1)) + + preds = np.tile(idx, (1, 1, 2)).astype(np.float32) + preds[:, :, 0] = preds[:, :, 0] % W + preds[:, :, 1] = preds[:, :, 1] // W + + preds = np.where(np.tile(maxvals, (1, 1, 2)) > 0.0, preds, -1) + return preds, maxvals + + +def _get_max_preds_3d(heatmaps): + """Get keypoint predictions from 3D score maps. + + Note: + batch size: N + num keypoints: K + heatmap depth size: D + heatmap height: H + heatmap width: W + + Args: + heatmaps (np.ndarray[N, K, D, H, W]): model predicted heatmaps. + + Returns: + tuple: A tuple containing aggregated results. + + - preds (np.ndarray[N, K, 3]): Predicted keypoint location. + - maxvals (np.ndarray[N, K, 1]): Scores (confidence) of the keypoints. + """ + assert isinstance(heatmaps, np.ndarray), \ + ('heatmaps should be numpy.ndarray') + assert heatmaps.ndim == 5, 'heatmaps should be 5-ndim' + + N, K, D, H, W = heatmaps.shape + heatmaps_reshaped = heatmaps.reshape((N, K, -1)) + idx = np.argmax(heatmaps_reshaped, 2).reshape((N, K, 1)) + maxvals = np.amax(heatmaps_reshaped, 2).reshape((N, K, 1)) + + preds = np.zeros((N, K, 3), dtype=np.float32) + _idx = idx[..., 0] + preds[..., 2] = _idx // (H * W) + preds[..., 1] = (_idx // W) % H + preds[..., 0] = _idx % W + + preds = np.where(maxvals > 0.0, preds, -1) + return preds, maxvals + + +def pose_pck_accuracy(output, target, mask, thr=0.05, normalize=None): + """Calculate the pose accuracy of PCK for each individual keypoint and the + averaged accuracy across all keypoints from heatmaps. + + Note: + PCK metric measures accuracy of the localization of the body joints. + The distances between predicted positions and the ground-truth ones + are typically normalized by the bounding box size. + The threshold (thr) of the normalized distance is commonly set + as 0.05, 0.1 or 0.2 etc. + + - batch_size: N + - num_keypoints: K + - heatmap height: H + - heatmap width: W + + Args: + output (np.ndarray[N, K, H, W]): Model output heatmaps. + target (np.ndarray[N, K, H, W]): Groundtruth heatmaps. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + thr (float): Threshold of PCK calculation. Default 0.05. + normalize (np.ndarray[N, 2]): Normalization factor for H&W. + + Returns: + tuple: A tuple containing keypoint accuracy. + + - np.ndarray[K]: Accuracy of each keypoint. + - float: Averaged accuracy across all keypoints. + - int: Number of valid keypoints. + """ + N, K, H, W = output.shape + if K == 0: + return None, 0, 0 + if normalize is None: + normalize = np.tile(np.array([[H, W]]), (N, 1)) + + pred, _ = _get_max_preds(output) + gt, _ = _get_max_preds(target) + return keypoint_pck_accuracy(pred, gt, mask, thr, normalize) + + +def keypoint_pck_accuracy(pred, gt, mask, thr, normalize): + """Calculate the pose accuracy of PCK for each individual keypoint and the + averaged accuracy across all keypoints for coordinates. + + Note: + PCK metric measures accuracy of the localization of the body joints. + The distances between predicted positions and the ground-truth ones + are typically normalized by the bounding box size. + The threshold (thr) of the normalized distance is commonly set + as 0.05, 0.1 or 0.2 etc. + + - batch_size: N + - num_keypoints: K + + Args: + pred (np.ndarray[N, K, 2]): Predicted keypoint location. + gt (np.ndarray[N, K, 2]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + thr (float): Threshold of PCK calculation. + normalize (np.ndarray[N, 2]): Normalization factor for H&W. + + Returns: + tuple: A tuple containing keypoint accuracy. + + - acc (np.ndarray[K]): Accuracy of each keypoint. + - avg_acc (float): Averaged accuracy across all keypoints. + - cnt (int): Number of valid keypoints. + """ + distances = _calc_distances(pred, gt, mask, normalize) + + acc = np.array([_distance_acc(d, thr) for d in distances]) + valid_acc = acc[acc >= 0] + cnt = len(valid_acc) + avg_acc = valid_acc.mean() if cnt > 0 else 0 + return acc, avg_acc, cnt + + +def keypoint_auc(pred, gt, mask, normalize, num_step=20): + """Calculate the pose accuracy of PCK for each individual keypoint and the + averaged accuracy across all keypoints for coordinates. + + Note: + - batch_size: N + - num_keypoints: K + + Args: + pred (np.ndarray[N, K, 2]): Predicted keypoint location. + gt (np.ndarray[N, K, 2]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + normalize (float): Normalization factor. + + Returns: + float: Area under curve. + """ + nor = np.tile(np.array([[normalize, normalize]]), (pred.shape[0], 1)) + x = [1.0 * i / num_step for i in range(num_step)] + y = [] + for thr in x: + _, avg_acc, _ = keypoint_pck_accuracy(pred, gt, mask, thr, nor) + y.append(avg_acc) + + auc = 0 + for i in range(num_step): + auc += 1.0 / num_step * y[i] + return auc + + +def keypoint_nme(pred, gt, mask, normalize_factor): + """Calculate the normalized mean error (NME). + + Note: + - batch_size: N + - num_keypoints: K + + Args: + pred (np.ndarray[N, K, 2]): Predicted keypoint location. + gt (np.ndarray[N, K, 2]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + normalize_factor (np.ndarray[N, 2]): Normalization factor. + + Returns: + float: normalized mean error + """ + distances = _calc_distances(pred, gt, mask, normalize_factor) + distance_valid = distances[distances != -1] + return distance_valid.sum() / max(1, len(distance_valid)) + + +def keypoint_epe(pred, gt, mask): + """Calculate the end-point error. + + Note: + - batch_size: N + - num_keypoints: K + + Args: + pred (np.ndarray[N, K, 2]): Predicted keypoint location. + gt (np.ndarray[N, K, 2]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + + Returns: + float: Average end-point error. + """ + + distances = _calc_distances( + pred, gt, mask, + np.ones((pred.shape[0], pred.shape[2]), dtype=np.float32)) + distance_valid = distances[distances != -1] + return distance_valid.sum() / max(1, len(distance_valid)) + + +def _taylor(heatmap, coord): + """Distribution aware coordinate decoding method. + + Note: + - heatmap height: H + - heatmap width: W + + Args: + heatmap (np.ndarray[H, W]): Heatmap of a particular joint type. + coord (np.ndarray[2,]): Coordinates of the predicted keypoints. + + Returns: + np.ndarray[2,]: Updated coordinates. + """ + H, W = heatmap.shape[:2] + px, py = int(coord[0]), int(coord[1]) + if 1 < px < W - 2 and 1 < py < H - 2: + dx = 0.5 * (heatmap[py][px + 1] - heatmap[py][px - 1]) + dy = 0.5 * (heatmap[py + 1][px] - heatmap[py - 1][px]) + dxx = 0.25 * ( + heatmap[py][px + 2] - 2 * heatmap[py][px] + heatmap[py][px - 2]) + dxy = 0.25 * ( + heatmap[py + 1][px + 1] - heatmap[py - 1][px + 1] - + heatmap[py + 1][px - 1] + heatmap[py - 1][px - 1]) + dyy = 0.25 * ( + heatmap[py + 2 * 1][px] - 2 * heatmap[py][px] + + heatmap[py - 2 * 1][px]) + derivative = np.array([[dx], [dy]]) + hessian = np.array([[dxx, dxy], [dxy, dyy]]) + if dxx * dyy - dxy**2 != 0: + hessianinv = np.linalg.inv(hessian) + offset = -hessianinv @ derivative + offset = np.squeeze(np.array(offset.T), axis=0) + coord += offset + return coord + + +def post_dark_udp(coords, batch_heatmaps, kernel=3): + """DARK post-pocessing. Implemented by udp. Paper ref: Huang et al. The + Devil is in the Details: Delving into Unbiased Data Processing for Human + Pose Estimation (CVPR 2020). Zhang et al. Distribution-Aware Coordinate + Representation for Human Pose Estimation (CVPR 2020). + + Note: + - batch size: B + - num keypoints: K + - num persons: N + - height of heatmaps: H + - width of heatmaps: W + + B=1 for bottom_up paradigm where all persons share the same heatmap. + B=N for top_down paradigm where each person has its own heatmaps. + + Args: + coords (np.ndarray[N, K, 2]): Initial coordinates of human pose. + batch_heatmaps (np.ndarray[B, K, H, W]): batch_heatmaps + kernel (int): Gaussian kernel size (K) for modulation. + + Returns: + np.ndarray([N, K, 2]): Refined coordinates. + """ + if not isinstance(batch_heatmaps, np.ndarray): + batch_heatmaps = batch_heatmaps.cpu().numpy() + B, K, H, W = batch_heatmaps.shape + N = coords.shape[0] + assert (B == 1 or B == N) + for heatmaps in batch_heatmaps: + for heatmap in heatmaps: + cv2.GaussianBlur(heatmap, (kernel, kernel), 0, heatmap) + np.clip(batch_heatmaps, 0.001, 50, batch_heatmaps) + np.log(batch_heatmaps, batch_heatmaps) + + batch_heatmaps_pad = np.pad( + batch_heatmaps, ((0, 0), (0, 0), (1, 1), (1, 1)), + mode='edge').flatten() + + index = coords[..., 0] + 1 + (coords[..., 1] + 1) * (W + 2) + index += (W + 2) * (H + 2) * np.arange(0, B * K).reshape(-1, K) + index = index.astype(int).reshape(-1, 1) + i_ = batch_heatmaps_pad[index] + ix1 = batch_heatmaps_pad[index + 1] + iy1 = batch_heatmaps_pad[index + W + 2] + ix1y1 = batch_heatmaps_pad[index + W + 3] + ix1_y1_ = batch_heatmaps_pad[index - W - 3] + ix1_ = batch_heatmaps_pad[index - 1] + iy1_ = batch_heatmaps_pad[index - 2 - W] + + dx = 0.5 * (ix1 - ix1_) + dy = 0.5 * (iy1 - iy1_) + derivative = np.concatenate([dx, dy], axis=1) + derivative = derivative.reshape(N, K, 2, 1) + dxx = ix1 - 2 * i_ + ix1_ + dyy = iy1 - 2 * i_ + iy1_ + dxy = 0.5 * (ix1y1 - ix1 - iy1 + i_ + i_ - ix1_ - iy1_ + ix1_y1_) + hessian = np.concatenate([dxx, dxy, dxy, dyy], axis=1) + hessian = hessian.reshape(N, K, 2, 2) + hessian = np.linalg.inv(hessian + np.finfo(np.float32).eps * np.eye(2)) + coords -= np.einsum('ijmn,ijnk->ijmk', hessian, derivative).squeeze() + return coords + + +def _gaussian_blur(heatmaps, kernel=11): + """Modulate heatmap distribution with Gaussian. + sigma = 0.3*((kernel_size-1)*0.5-1)+0.8 + sigma~=3 if k=17 + sigma=2 if k=11; + sigma~=1.5 if k=7; + sigma~=1 if k=3; + + Note: + - batch_size: N + - num_keypoints: K + - heatmap height: H + - heatmap width: W + + Args: + heatmaps (np.ndarray[N, K, H, W]): model predicted heatmaps. + kernel (int): Gaussian kernel size (K) for modulation, which should + match the heatmap gaussian sigma when training. + K=17 for sigma=3 and k=11 for sigma=2. + + Returns: + np.ndarray ([N, K, H, W]): Modulated heatmap distribution. + """ + assert kernel % 2 == 1 + + border = (kernel - 1) // 2 + batch_size = heatmaps.shape[0] + num_joints = heatmaps.shape[1] + height = heatmaps.shape[2] + width = heatmaps.shape[3] + for i in range(batch_size): + for j in range(num_joints): + origin_max = np.max(heatmaps[i, j]) + dr = np.zeros((height + 2 * border, width + 2 * border), + dtype=np.float32) + dr[border:-border, border:-border] = heatmaps[i, j].copy() + dr = cv2.GaussianBlur(dr, (kernel, kernel), 0) + heatmaps[i, j] = dr[border:-border, border:-border].copy() + heatmaps[i, j] *= origin_max / np.max(heatmaps[i, j]) + return heatmaps + + +def keypoints_from_regression(regression_preds, center, scale, img_size): + """Get final keypoint predictions from regression vectors and transform + them back to the image. + + Note: + - batch_size: N + - num_keypoints: K + + Args: + regression_preds (np.ndarray[N, K, 2]): model prediction. + center (np.ndarray[N, 2]): Center of the bounding box (x, y). + scale (np.ndarray[N, 2]): Scale of the bounding box + wrt height/width. + img_size (list(img_width, img_height)): model input image size. + + Returns: + tuple: + + - preds (np.ndarray[N, K, 2]): Predicted keypoint location in images. + - maxvals (np.ndarray[N, K, 1]): Scores (confidence) of the keypoints. + """ + N, K, _ = regression_preds.shape + preds, maxvals = regression_preds, np.ones((N, K, 1), dtype=np.float32) + + preds = preds * img_size + + # Transform back to the image + for i in range(N): + preds[i] = transform_preds(preds[i], center[i], scale[i], img_size) + + return preds, maxvals + + +def keypoints_from_heatmaps(heatmaps, + center, + scale, + unbiased=False, + post_process='default', + kernel=11, + valid_radius_factor=0.0546875, + use_udp=False, + target_type='GaussianHeatmap'): + """Get final keypoint predictions from heatmaps and transform them back to + the image. + + Note: + - batch size: N + - num keypoints: K + - heatmap height: H + - heatmap width: W + + Args: + heatmaps (np.ndarray[N, K, H, W]): model predicted heatmaps. + center (np.ndarray[N, 2]): Center of the bounding box (x, y). + scale (np.ndarray[N, 2]): Scale of the bounding box + wrt height/width. + post_process (str/None): Choice of methods to post-process + heatmaps. Currently supported: None, 'default', 'unbiased', + 'megvii'. + unbiased (bool): Option to use unbiased decoding. Mutually + exclusive with megvii. + Note: this arg is deprecated and unbiased=True can be replaced + by post_process='unbiased' + Paper ref: Zhang et al. Distribution-Aware Coordinate + Representation for Human Pose Estimation (CVPR 2020). + kernel (int): Gaussian kernel size (K) for modulation, which should + match the heatmap gaussian sigma when training. + K=17 for sigma=3 and k=11 for sigma=2. + valid_radius_factor (float): The radius factor of the positive area + in classification heatmap for UDP. + use_udp (bool): Use unbiased data processing. + target_type (str): 'GaussianHeatmap' or 'CombinedTarget'. + GaussianHeatmap: Classification target with gaussian distribution. + CombinedTarget: The combination of classification target + (response map) and regression target (offset map). + Paper ref: Huang et al. The Devil is in the Details: Delving into + Unbiased Data Processing for Human Pose Estimation (CVPR 2020). + + Returns: + tuple: A tuple containing keypoint predictions and scores. + + - preds (np.ndarray[N, K, 2]): Predicted keypoint location in images. + - maxvals (np.ndarray[N, K, 1]): Scores (confidence) of the keypoints. + """ + # Avoid being affected + heatmaps = heatmaps.copy() + + # detect conflicts + if unbiased: + assert post_process not in [False, None, 'megvii'] + if post_process in ['megvii', 'unbiased']: + assert kernel > 0 + if use_udp: + assert not post_process == 'megvii' + + # normalize configs + if post_process is False: + warnings.warn( + 'post_process=False is deprecated, ' + 'please use post_process=None instead', DeprecationWarning) + post_process = None + elif post_process is True: + if unbiased is True: + warnings.warn( + 'post_process=True, unbiased=True is deprecated,' + " please use post_process='unbiased' instead", + DeprecationWarning) + post_process = 'unbiased' + else: + warnings.warn( + 'post_process=True, unbiased=False is deprecated, ' + "please use post_process='default' instead", + DeprecationWarning) + post_process = 'default' + elif post_process == 'default': + if unbiased is True: + warnings.warn( + 'unbiased=True is deprecated, please use ' + "post_process='unbiased' instead", DeprecationWarning) + post_process = 'unbiased' + + # start processing + if post_process == 'megvii': + heatmaps = _gaussian_blur(heatmaps, kernel=kernel) + + N, K, H, W = heatmaps.shape + if use_udp: + if target_type.lower() == 'GaussianHeatMap'.lower(): + preds, maxvals = _get_max_preds(heatmaps) + preds = post_dark_udp(preds, heatmaps, kernel=kernel) + elif target_type.lower() == 'CombinedTarget'.lower(): + for person_heatmaps in heatmaps: + for i, heatmap in enumerate(person_heatmaps): + kt = 2 * kernel + 1 if i % 3 == 0 else kernel + cv2.GaussianBlur(heatmap, (kt, kt), 0, heatmap) + # valid radius is in direct proportion to the height of heatmap. + valid_radius = valid_radius_factor * H + offset_x = heatmaps[:, 1::3, :].flatten() * valid_radius + offset_y = heatmaps[:, 2::3, :].flatten() * valid_radius + heatmaps = heatmaps[:, ::3, :] + preds, maxvals = _get_max_preds(heatmaps) + index = preds[..., 0] + preds[..., 1] * W + index += W * H * np.arange(0, N * K / 3) + index = index.astype(int).reshape(N, K // 3, 1) + preds += np.concatenate((offset_x[index], offset_y[index]), axis=2) + else: + raise ValueError('target_type should be either ' + "'GaussianHeatmap' or 'CombinedTarget'") + else: + preds, maxvals = _get_max_preds(heatmaps) + if post_process == 'unbiased': # alleviate biased coordinate + # apply Gaussian distribution modulation. + heatmaps = np.log( + np.maximum(_gaussian_blur(heatmaps, kernel), 1e-10)) + for n in range(N): + for k in range(K): + preds[n][k] = _taylor(heatmaps[n][k], preds[n][k]) + elif post_process is not None: + # add +/-0.25 shift to the predicted locations for higher acc. + for n in range(N): + for k in range(K): + heatmap = heatmaps[n][k] + px = int(preds[n][k][0]) + py = int(preds[n][k][1]) + if 1 < px < W - 1 and 1 < py < H - 1: + diff = np.array([ + heatmap[py][px + 1] - heatmap[py][px - 1], + heatmap[py + 1][px] - heatmap[py - 1][px] + ]) + preds[n][k] += np.sign(diff) * .25 + if post_process == 'megvii': + preds[n][k] += 0.5 + + # Transform back to the image + for i in range(N): + preds[i] = transform_preds( + preds[i], center[i], scale[i], [W, H], use_udp=use_udp) + + if post_process == 'megvii': + maxvals = maxvals / 255.0 + 0.5 + + return preds, maxvals + + +def keypoints_from_heatmaps3d(heatmaps, center, scale): + """Get final keypoint predictions from 3d heatmaps and transform them back + to the image. + + Note: + - batch size: N + - num keypoints: K + - heatmap depth size: D + - heatmap height: H + - heatmap width: W + + Args: + heatmaps (np.ndarray[N, K, D, H, W]): model predicted heatmaps. + center (np.ndarray[N, 2]): Center of the bounding box (x, y). + scale (np.ndarray[N, 2]): Scale of the bounding box + wrt height/width. + + Returns: + tuple: A tuple containing keypoint predictions and scores. + + - preds (np.ndarray[N, K, 3]): Predicted 3d keypoint location \ + in images. + - maxvals (np.ndarray[N, K, 1]): Scores (confidence) of the keypoints. + """ + N, K, D, H, W = heatmaps.shape + preds, maxvals = _get_max_preds_3d(heatmaps) + # Transform back to the image + for i in range(N): + preds[i, :, :2] = transform_preds(preds[i, :, :2], center[i], scale[i], + [W, H]) + return preds, maxvals + + +def multilabel_classification_accuracy(pred, gt, mask, thr=0.5): + """Get multi-label classification accuracy. + + Note: + - batch size: N + - label number: L + + Args: + pred (np.ndarray[N, L, 2]): model predicted labels. + gt (np.ndarray[N, L, 2]): ground-truth labels. + mask (np.ndarray[N, 1] or np.ndarray[N, L] ): reliability of + ground-truth labels. + + Returns: + float: multi-label classification accuracy. + """ + # we only compute accuracy on the samples with ground-truth of all labels. + valid = (mask > 0).min(axis=1) if mask.ndim == 2 else (mask > 0) + pred, gt = pred[valid], gt[valid] + + if pred.shape[0] == 0: + acc = 0.0 # when no sample is with gt labels, set acc to 0. + else: + # The classification of a sample is regarded as correct + # only if it's correct for all labels. + acc = (((pred - thr) * (gt - thr)) > 0).all(axis=1).mean() + return acc diff --git a/easy_ViTPose/vit_utils/train_valid_fn.py b/easy_ViTPose/vit_utils/train_valid_fn.py new file mode 100644 index 0000000000000000000000000000000000000000..2c84302df15cb43e9dd9eb0e7af55c25b2244fae --- /dev/null +++ b/easy_ViTPose/vit_utils/train_valid_fn.py @@ -0,0 +1,162 @@ +import os.path as osp + +import torch +import torch.nn as nn + +from vit_models.losses import JointsMSELoss +from vit_models.optimizer import LayerDecayOptimizer + +from torch.nn.parallel import DataParallel, DistributedDataParallel +from torch.nn.utils import clip_grad_norm_ +from torch.optim import AdamW +from torch.optim.lr_scheduler import LambdaLR, MultiStepLR +from torch.utils.data import DataLoader, Dataset +from torch.utils.data.distributed import DistributedSampler +from torch.cuda.amp import autocast, GradScaler +from tqdm import tqdm +from time import time + +from vit_utils.dist_util import get_dist_info, init_dist +from vit_utils.logging import get_root_logger + +@torch.no_grad() +def valid_model(model: nn.Module, dataloaders: DataLoader, criterion: nn.Module, cfg: dict) -> None: + total_loss = 0 + total_metric = 0 + model.eval() + for dataloader in dataloaders: + for batch_idx, batch in enumerate(dataloader): + images, targets, target_weights, __ = batch + images = images.to('cuda') + targets = targets.to('cuda') + target_weights = target_weights.to('cuda') + + outputs = model(images) + loss = criterion(outputs, targets, target_weights) + total_loss += loss.item() + + avg_loss = total_loss/(len(dataloader)*len(dataloaders)) + return avg_loss + +def train_model(model: nn.Module, datasets_train: Dataset, datasets_valid: Dataset, cfg: dict, distributed: bool, validate: bool, timestamp: str, meta: dict) -> None: + logger = get_root_logger() + + # Prepare data loaders + datasets_train = datasets_train if isinstance(datasets_train, (list, tuple)) else [datasets_train] + datasets_valid = datasets_valid if isinstance(datasets_valid, (list, tuple)) else [datasets_valid] + + if distributed: + samplers_train = [DistributedSampler(ds, num_replicas=len(cfg.gpu_ids), rank=torch.cuda.current_device(), shuffle=True, drop_last=False) for ds in datasets_train] + samplers_valid = [DistributedSampler(ds, num_replicas=len(cfg.gpu_ids), rank=torch.cuda.current_device(), shuffle=False, drop_last=False) for ds in datasets_valid] + else: + samplers_train = [None for ds in datasets_train] + samplers_valid = [None for ds in datasets_valid] + + dataloaders_train = [DataLoader(ds, batch_size=cfg.data['samples_per_gpu'], shuffle=True, sampler=sampler, num_workers=cfg.data['workers_per_gpu'], pin_memory=False) for ds, sampler in zip(datasets_train, samplers_train)] + dataloaders_valid = [DataLoader(ds, batch_size=cfg.data['samples_per_gpu'], shuffle=False, sampler=sampler, num_workers=cfg.data['workers_per_gpu'], pin_memory=False) for ds, sampler in zip(datasets_valid, samplers_valid)] + + # put model on gpus + if distributed: + find_unused_parameters = cfg.get('find_unused_parameters', False) + # Sets the `find_unused_parameters` parameter in + # torch.nn.parallel.DistributedDataParallel + + model = DistributedDataParallel( + module=model, + device_ids=[torch.cuda.current_device()], + broadcast_buffers=False, + find_unused_parameters=find_unused_parameters) + else: + model = DataParallel(model, device_ids=cfg.gpu_ids) + + # Loss function + criterion = JointsMSELoss(use_target_weight=cfg.model['keypoint_head']['loss_keypoint']['use_target_weight']) + + # Optimizer + optimizer = AdamW(model.parameters(), lr=cfg.optimizer['lr'], betas=cfg.optimizer['betas'], weight_decay=cfg.optimizer['weight_decay']) + + # Layer-wise learning rate decay + lr_mult = [cfg.optimizer['paramwise_cfg']['layer_decay_rate']] * cfg.optimizer['paramwise_cfg']['num_layers'] + layerwise_optimizer = LayerDecayOptimizer(optimizer, lr_mult) + + + # Learning rate scheduler (MultiStepLR) + milestones = cfg.lr_config['step'] + gamma = 0.1 + scheduler = MultiStepLR(optimizer, milestones, gamma) + + # Warm-up scheduler + num_warmup_steps = cfg.lr_config['warmup_iters'] # Number of warm-up steps + warmup_factor = cfg.lr_config['warmup_ratio'] # Initial learning rate = warmup_factor * learning_rate + warmup_scheduler = LambdaLR( + optimizer, + lr_lambda=lambda step: warmup_factor + (1.0 - warmup_factor) * step / num_warmup_steps + ) + + # AMP setting + if cfg.use_amp: + logger.info("Using Automatic Mixed Precision (AMP) training...") + # Create a GradScaler object for FP16 training + scaler = GradScaler() + + # Logging config + total_params = sum(p.numel() for p in model.parameters() if p.requires_grad) + logger.info(f'''\n + #========= [Train Configs] =========# + # - Num GPUs: {len(cfg.gpu_ids)} + # - Batch size (per gpu): {cfg.data['samples_per_gpu']} + # - LR: {cfg.optimizer['lr']: .6f} + # - Num params: {total_params:,d} + # - AMP: {cfg.use_amp} + #===================================# + ''') + + global_step = 0 + for dataloader in dataloaders_train: + for epoch in range(cfg.total_epochs): + model.train() + train_pbar = tqdm(dataloader) + total_loss = 0 + tic = time() + for batch_idx, batch in enumerate(train_pbar): + layerwise_optimizer.zero_grad() + + images, targets, target_weights, __ = batch + images = images.to('cuda') + targets = targets.to('cuda') + target_weights = target_weights.to('cuda') + + if cfg.use_amp: + with autocast(): + outputs = model(images) + loss = criterion(outputs, targets, target_weights) + scaler.scale(loss).backward() + clip_grad_norm_(model.parameters(), **cfg.optimizer_config['grad_clip']) + scaler.step(layerwise_optimizer) + scaler.update() + else: + outputs = model(images) + loss = criterion(outputs, targets, target_weights) + loss.backward() + clip_grad_norm_(model.parameters(), **cfg.optimizer_config['grad_clip']) + layerwise_optimizer.step() + + if global_step < num_warmup_steps: + warmup_scheduler.step() + global_step += 1 + + total_loss += loss.item() + train_pbar.set_description(f"🏋️> Epoch [{str(epoch).zfill(3)}/{str(cfg.total_epochs).zfill(3)}] | Loss {loss.item():.4f} | LR {optimizer.param_groups[0]['lr']:.6f} | Step") + scheduler.step() + + avg_loss_train = total_loss/len(dataloader) + logger.info(f"[Summary-train] Epoch [{str(epoch).zfill(3)}/{str(cfg.total_epochs).zfill(3)}] | Average Loss (train) {avg_loss_train:.4f} --- {time()-tic:.5f} sec. elapsed") + ckpt_name = f"epoch{str(epoch).zfill(3)}.pth" + ckpt_path = osp.join(cfg.work_dir, ckpt_name) + torch.save(model.module.state_dict(), ckpt_path) + + # validation + if validate: + tic2 = time() + avg_loss_valid = valid_model(model, dataloaders_valid, criterion, cfg) + logger.info(f"[Summary-valid] Epoch [{str(epoch).zfill(3)}/{str(cfg.total_epochs).zfill(3)}] | Average Loss (valid) {avg_loss_valid:.4f} --- {time()-tic2:.5f} sec. elapsed") diff --git a/easy_ViTPose/vit_utils/transform.py b/easy_ViTPose/vit_utils/transform.py new file mode 100644 index 0000000000000000000000000000000000000000..3c153eeef4761cdde5fc081e5b7c72d2d11f394d --- /dev/null +++ b/easy_ViTPose/vit_utils/transform.py @@ -0,0 +1,96 @@ +import math +import cv2 +import munkres +import numpy as np +import torch + + +# solution proposed in https://github.com/pytorch/pytorch/issues/229#issuecomment-299424875 +def flip_tensor(tensor, dim=0): + """ + flip the tensor on the dimension dim + """ + inv_idx = torch.arange(tensor.shape[dim] - 1, -1, -1).to(tensor.device) + return tensor.index_select(dim, inv_idx) + + +# +# derived from https://github.com/leoxiaobin/deep-high-resolution-net.pytorch +def flip_back(output_flipped, matched_parts): + assert len(output_flipped.shape) == 4, 'output_flipped has to be [batch_size, num_joints, height, width]' + + output_flipped = flip_tensor(output_flipped, dim=-1) + + for pair in matched_parts: + tmp = output_flipped[:, pair[0]].clone() + output_flipped[:, pair[0]] = output_flipped[:, pair[1]] + output_flipped[:, pair[1]] = tmp + + return output_flipped + + +def fliplr_joints(joints, joints_vis, width, matched_parts): + # Flip horizontal + joints[:, 0] = width - joints[:, 0] - 1 + + # Change left-right parts + for pair in matched_parts: + joints[pair[0], :], joints[pair[1], :] = \ + joints[pair[1], :], joints[pair[0], :].copy() + joints_vis[pair[0], :], joints_vis[pair[1], :] = \ + joints_vis[pair[1], :], joints_vis[pair[0], :].copy() + + return joints * joints_vis, joints_vis + + +def get_affine_transform(center, scale, pixel_std, rot, output_size, shift=np.array([0, 0], dtype=np.float32), inv=0): + if not isinstance(scale, np.ndarray) and not isinstance(scale, list): + print(scale) + scale = np.array([scale, scale]) + + scale_tmp = scale * 1.0 * pixel_std # It was scale_tmp = scale * 200.0 + src_w = scale_tmp[0] + dst_w = output_size[0] + dst_h = output_size[1] + + rot_rad = np.pi * rot / 180 + src_dir = get_dir([0, src_w * -0.5], rot_rad) + dst_dir = np.array([0, dst_w * -0.5], np.float32) + + src = np.zeros((3, 2), dtype=np.float32) + dst = np.zeros((3, 2), dtype=np.float32) + src[0, :] = center + scale_tmp * shift + src[1, :] = center + src_dir + scale_tmp * shift + dst[0, :] = [dst_w * 0.5, dst_h * 0.5] + dst[1, :] = np.array([dst_w * 0.5, dst_h * 0.5]) + dst_dir + + src[2:, :] = get_3rd_point(src[0, :], src[1, :]) + dst[2:, :] = get_3rd_point(dst[0, :], dst[1, :]) + + if inv: + trans = cv2.getAffineTransform(np.float32(dst), np.float32(src)) + else: + trans = cv2.getAffineTransform(np.float32(src), np.float32(dst)) + + return trans + + +def affine_transform(pt, t): + new_pt = np.array([pt[0], pt[1], 1.]).T + new_pt = np.dot(t, new_pt) + return new_pt[:2] + + +def get_3rd_point(a, b): + direct = a - b + return b + np.array([-direct[1], direct[0]], dtype=np.float32) + + +def get_dir(src_point, rot_rad): + sn, cs = np.sin(rot_rad), np.cos(rot_rad) + + src_result = [0, 0] + src_result[0] = src_point[0] * cs - src_point[1] * sn + src_result[1] = src_point[0] * sn + src_point[1] * cs + + return src_result diff --git a/easy_ViTPose/vit_utils/util.py b/easy_ViTPose/vit_utils/util.py new file mode 100644 index 0000000000000000000000000000000000000000..c353cc67a725662a4ce0ba983fce55b1c08d29cf --- /dev/null +++ b/easy_ViTPose/vit_utils/util.py @@ -0,0 +1,265 @@ +from collections import OrderedDict +from importlib import import_module +import os +import random +import re +import warnings +from typing import Union, Any + +import numpy as np +import torch +from torch import distributed as dist +import torch.nn as nn +from torch.nn.parallel import DataParallel, DistributedDataParallel + +from .dist_util import get_dist_info + +MODULE_WRAPPERS = [DataParallel, DistributedDataParallel] + + +MODEL_ABBR_MAP = { + 's': 'small', + 'b': 'base', + 'l': 'large', + 'h': 'huge' +} + + +def infer_dataset_by_path(model_path: str) -> Union[str, Any]: + model = os.path.basename(model_path) + p = r'-([a-zA-Z0-9_]+)\.[pth, onnx, engine]' + m = re.search(p, model) + if not m: + raise ValueError('Could not infer the dataset from ckpt name, specify it') + return m.group(1) + + +def dyn_model_import(dataset: str, model: str): + config_name = f'configs.ViTPose_{dataset}' + imp = import_module(config_name) + model = f'model_{MODEL_ABBR_MAP[model]}' + return getattr(imp, model) + + +def init_random_seed(seed=None, device='cuda'): + """Initialize random seed. + + If the seed is not set, the seed will be automatically randomized, + and then broadcast to all processes to prevent some potential bugs. + + Args: + seed (int, Optional): The seed. Default to None. + device (str): The device where the seed will be put on. + Default to 'cuda'. + + Returns: + int: Seed to be used. + """ + if seed is not None: + return seed + + # Make sure all ranks share the same random seed to prevent + # some potential bugs. Please refer to + # https://github.com/open-mmlab/mmdetection/issues/6339 + rank, world_size = get_dist_info() + seed = np.random.randint(2**31) + if world_size == 1: + return seed + + if rank == 0: + random_num = torch.tensor(seed, dtype=torch.int32, device=device) + else: + random_num = torch.tensor(0, dtype=torch.int32, device=device) + dist.broadcast(random_num, src=0) + return random_num.item() + + +def set_random_seed(seed: int, + deterministic: bool = False, + use_rank_shift: bool = False) -> None: + """Set random seed. + + Args: + seed (int): Seed to be used. + deterministic (bool): Whether to set the deterministic option for + CUDNN backend, i.e., set `torch.backends.cudnn.deterministic` + to True and `torch.backends.cudnn.benchmark` to False. + Default: False. + rank_shift (bool): Whether to add rank number to the random seed to + have different random seed in different threads. Default: False. + """ + if use_rank_shift: + rank, _ = get_dist_info() + seed += rank + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + os.environ['PYTHONHASHSEED'] = str(seed) + if deterministic: + torch.backends.cudnn.deterministic = True + torch.backends.cudnn.benchmark = False + + +def is_module_wrapper(module: nn.Module) -> bool: + """ Check if module wrrapper exists recursively """ + def is_module_in_wrapper(module, module_wrapper): + module_wrappers = tuple(module_wrapper.module_dict.values()) + if isinstance(module, module_wrappers): + return True + for child in module_wrapper.children.values(): + if is_module_in_wrapper(module, child): + return True + return is_module_in_wrapper(module, MODULE_WRAPPERS) + + +def load_state_dict(module, state_dict, strict=False, logger=None): + """Load state_dict to a module. + + This method is modified from :meth:`torch.nn.Module.load_state_dict`. + Default value for ``strict`` is set to ``False`` and the message for + param mismatch will be shown even if strict is False. + + Args: + module (Module): Module that receives the state_dict. + state_dict (OrderedDict): Weights. + strict (bool): whether to strictly enforce that the keys + in :attr:`state_dict` match the keys returned by this module's + :meth:`~torch.nn.Module.state_dict` function. Default: ``False``. + logger (:obj:`logging.Logger`, optional): Logger to log the error + message. If not specified, print function will be used. + """ + unexpected_keys = [] + all_missing_keys = [] + err_msg = [] + + metadata = getattr(state_dict, '_metadata', None) + state_dict = state_dict.copy() + if metadata is not None: + state_dict._metadata = metadata + + # use _load_from_state_dict to enable checkpoint version control + def load(module, prefix=''): + # recursively check parallel module in case that the model has a + # complicated structure, e.g., nn.Module(nn.Module(DDP)) + if is_module_wrapper(module): + module = module.module + local_metadata = {} if metadata is None else metadata.get( + prefix[:-1], {}) + module._load_from_state_dict(state_dict, prefix, local_metadata, True, + all_missing_keys, unexpected_keys, + err_msg) + for name, child in module._modules.items(): + if child is not None: + load(child, prefix + name + '.') + + load(module) + load = None # break load->load reference cycle + + # ignore "num_batches_tracked" of BN layers + missing_keys = [ + key for key in all_missing_keys if 'num_batches_tracked' not in key + ] + + if unexpected_keys: + err_msg.append('unexpected key in source ' + f'state_dict: {", ".join(unexpected_keys)}\n') + if missing_keys: + err_msg.append( + f'missing keys in source state_dict: {", ".join(missing_keys)}\n') + + rank, _ = get_dist_info() + if len(err_msg) > 0 and rank == 0: + err_msg.insert( + 0, 'The model and loaded state dict do not match exactly\n') + err_msg = '\n'.join(err_msg) + if strict: + raise RuntimeError(err_msg) + elif logger is not None: + logger.warning(err_msg) + else: + print(err_msg) + + +def load_checkpoint(model, + filename, + map_location='cpu', + strict=False, + logger=None): + """Load checkpoint from a file or URI. + + Args: + model (Module): Module to load checkpoint. + filename (str): Accept local filepath, URL, ``torchvision://xxx``, + ``open-mmlab://xxx``. + map_location (str): Same as :func:`torch.load`. + strict (bool): Whether to allow different params for the model and + checkpoint. + logger (:mod:`logging.Logger` or None): The logger for error message. + + Returns: + dict or OrderedDict: The loaded checkpoint. + """ + checkpoint = torch.load(filename, map_location=map_location) + # OrderedDict is a subclass of dict + if not isinstance(checkpoint, dict): + raise RuntimeError( + f'No state_dict found in checkpoint file {filename}') + # get state_dict from checkpoint + if 'state_dict' in checkpoint: + state_dict_tmp = checkpoint['state_dict'] + else: + state_dict_tmp = checkpoint + + state_dict = OrderedDict() + # strip prefix of state_dict + for k, v in state_dict_tmp.items(): + if k.startswith('module.backbone.'): + state_dict[k[16:]] = v + elif k.startswith('module.'): + state_dict[k[7:]] = v + elif k.startswith('backbone.'): + state_dict[k[9:]] = v + else: + state_dict[k] = v + # load state_dict + load_state_dict(model, state_dict, strict, logger) + return checkpoint + + +def resize(input, + size=None, + scale_factor=None, + mode='nearest', + align_corners=None, + warning=True): + if warning: + if size is not None and align_corners: + input_h, input_w = int(input.shape[0]), int(input.shape[1]) + output_h, output_w = int(size[0]), int(size[1]) + if output_h > input_h or output_w > output_h: + if ((output_h > 1 and output_w > 1 and input_h > 1 + and input_w > 1) and (output_h - 1) % (input_h - 1) + and (output_w - 1) % (input_w - 1)): + warnings.warn( + f'When align_corners={align_corners}, ' + 'the output would more aligned if ' + f'input size {(input_h, input_w)} is `x+1` and ' + f'out size {(output_h, output_w)} is `nx+1`') + +def constant_init(module: nn.Module, val: float, bias: float = 0) -> None: + if hasattr(module, 'weight') and module.weight is not None: + nn.init.constant_(module.weight, val) + if hasattr(module, 'bias') and module.bias is not None: + nn.init.constant_(module.bias, bias) + + +def normal_init(module: nn.Module, + mean: float = 0, + std: float = 1, + bias: float = 0) -> None: + if hasattr(module, 'weight') and module.weight is not None: + nn.init.normal_(module.weight, mean, std) + if hasattr(module, 'bias') and module.bias is not None: + nn.init.constant_(module.bias, bias) diff --git a/easy_ViTPose/vit_utils/visualization.py b/easy_ViTPose/vit_utils/visualization.py new file mode 100644 index 0000000000000000000000000000000000000000..fe404d743b62a37320a37394ce8440cf30bd63fe --- /dev/null +++ b/easy_ViTPose/vit_utils/visualization.py @@ -0,0 +1,556 @@ +import cv2 +import matplotlib.pyplot as plt +import numpy as np +import torchvision +import ffmpeg + + +__all__ = ["joints_dict", "draw_points_and_skeleton"] + + +def joints_dict(): + joints = { + "coco_25": { + "keypoints": { + 0: "nose", + 1: "left_eye", + 2: "right_eye", + 3: "left_ear", + 4: "right_ear", + 5: "neck", + 6: "left_shoulder", + 7: "right_shoulder", + 8: "left_elbow", + 9: "right_elbow", + 10: "left_wrist", + 11: "right_wrist", + 12: "left_hip", + 13: "right_hip", + 14: "hip", + 15: "left_knee", + 16: "right_knee", + 17: "left_ankle", + 18: "right_ankle", + 19: "left_big toe", + 20: "left_small_toe", + 21: "left_heel", + 22: "right_big_toe", + 23: "right_small_toe", + 24: "right_heel", + }, + "skeleton": [ + [17, 15], [15, 12], [18, 16], [16, 13], [12, 14], [13, 14], [5, 14], + [6, 5], [7, 5], [6, 8], [7, 9], [8, 10], [9, 11], [1, 2], [0, 1], [0, 2], + [1, 3], [2, 4], [17, 21], [18, 24], [19, 20], [22, 23], [19, 21], + [22, 24], [5, 0] + ] + }, + + "coco": { + "keypoints": { + 0: "nose", + 1: "left_eye", + 2: "right_eye", + 3: "left_ear", + 4: "right_ear", + 5: "left_shoulder", + 6: "right_shoulder", + 7: "left_elbow", + 8: "right_elbow", + 9: "left_wrist", + 10: "right_wrist", + 11: "left_hip", + 12: "right_hip", + 13: "left_knee", + 14: "right_knee", + 15: "left_ankle", + 16: "right_ankle" + }, + "skeleton": [ + [15, 13], [13, 11], [16, 14], [14, 12], [11, 12], [5, 11], [6, 12], + [5, 6], [5, 7], [6, 8], [7, 9], [8, 10], [1, 2], [0, 1], + [0, 2], [1, 3], [2, 4], [0, 5], [0, 6] + ] + }, + + "mpii": { + "keypoints": { + 0: "right_ankle", + 1: "right_knee", + 2: "right_hip", + 3: "left_hip", + 4: "left_knee", + 5: "left_ankle", + 6: "pelvis", + 7: "thorax", + 8: "upper_neck", + 9: "head top", + 10: "right_wrist", + 11: "right_elbow", + 12: "right_shoulder", + 13: "left_shoulder", + 14: "left_elbow", + 15: "left_wrist" + }, + "skeleton": [ + [5, 4], [4, 3], [0, 1], [1, 2], [3, 2], [3, 6], [2, 6], [6, 7], + [7, 8], [8, 9], [13, 7], [12, 7], [13, 14], [12, 11], [14, 15], + [11, 10], + ] + }, + + 'ap10k': { + 'keypoints': { + 0: 'L_Eye', + 1: 'R_Eye', + 2: 'Nose', + 3: 'Neck', + 4: 'Root of tail', + 5: 'L_Shoulder', + 6: 'L_Elbow', + 7: 'L_F_Paw', + 8: 'R_Shoulder', + 9: 'R_Elbow', + 10: 'R_F_Paw', + 11: 'L_Hip', + 12: 'L_Knee', + 13: 'L_B_Paw', + 14: 'R_Hip', + 15: 'R_Knee', + 16: 'R_B_Paw' + }, + 'skeleton': [ + [0, 1], [0, 2], [1, 2], [2, 3], [3, 4], [3, 5], [5, 6], [6, 7], + [3, 8], [8, 9], [9, 10], [4, 11], [11, 12], [12, 13], [4, 14], + [14, 15], [15, 16] + ] + }, + + 'apt36k': { + 'keypoints': { + 0: 'L_Eye', + 1: 'R_Eye', + 2: 'Nose', + 3: 'Neck', + 4: 'Root of tail', + 5: 'L_Shoulder', + 6: 'L_Elbow', + 7: 'L_F_Paw', + 8: 'R_Shoulder', + 9: 'R_Elbow', + 10: 'R_F_Paw', + 11: 'L_Hip', + 12: 'L_Knee', + 13: 'L_B_Paw', + 14: 'R_Hip', + 15: 'R_Knee', + 16: 'R_B_Paw' + }, + 'skeleton': [ + [0, 1], [0, 2], [1, 2], [2, 3], [3, 4], [3, 5], [5, 6], [6, 7], + [3, 8], [8, 9], [9, 10], [4, 11], [11, 12], [12, 13], [4, 14], + [14, 15], [15, 16] + ] + }, + + 'aic': { + 'keypoints': { + 0: 'right_shoulder', + 1: 'right_elbow', + 2: 'right_wrist', + 3: 'left_shoulder', + 4: 'left_elbow', + 5: 'left_wrist', + 6: 'right_hip', + 7: 'right_knee', + 8: 'right_ankle', + 9: 'left_hip', + 10: 'left_knee', + 11: 'left_ankle', + 12: 'head_top', + 13: 'neck' + }, + 'skeleton': [ + [2, 1], [1, 0], [0, 13], [13, 3], [3, 4], [4, 5], [8, 7], + [7, 6], [6, 9], [9, 10], [10, 11], [12, 13], [0, 6], [3, 9] + ] + }, + + 'wholebody': { + 'keypoints': { + 0: 'nose', + 1: 'left_eye', + 2: 'right_eye', + 3: 'left_ear', + 4: 'right_ear', + 5: 'left_shoulder', + 6: 'right_shoulder', + 7: 'left_elbow', + 8: 'right_elbow', + 9: 'left_wrist', + 10: 'right_wrist', + 11: 'left_hip', + 12: 'right_hip', + 13: 'left_knee', + 14: 'right_knee', + 15: 'left_ankle', + 16: 'right_ankle', + 17: 'left_big_toe', + 18: 'left_small_toe', + 19: 'left_heel', + 20: 'right_big_toe', + 21: 'right_small_toe', + 22: 'right_heel', + 23: 'face-0', + 24: 'face-1', + 25: 'face-2', + 26: 'face-3', + 27: 'face-4', + 28: 'face-5', + 29: 'face-6', + 30: 'face-7', + 31: 'face-8', + 32: 'face-9', + 33: 'face-10', + 34: 'face-11', + 35: 'face-12', + 36: 'face-13', + 37: 'face-14', + 38: 'face-15', + 39: 'face-16', + 40: 'face-17', + 41: 'face-18', + 42: 'face-19', + 43: 'face-20', + 44: 'face-21', + 45: 'face-22', + 46: 'face-23', + 47: 'face-24', + 48: 'face-25', + 49: 'face-26', + 50: 'face-27', + 51: 'face-28', + 52: 'face-29', + 53: 'face-30', + 54: 'face-31', + 55: 'face-32', + 56: 'face-33', + 57: 'face-34', + 58: 'face-35', + 59: 'face-36', + 60: 'face-37', + 61: 'face-38', + 62: 'face-39', + 63: 'face-40', + 64: 'face-41', + 65: 'face-42', + 66: 'face-43', + 67: 'face-44', + 68: 'face-45', + 69: 'face-46', + 70: 'face-47', + 71: 'face-48', + 72: 'face-49', + 73: 'face-50', + 74: 'face-51', + 75: 'face-52', + 76: 'face-53', + 77: 'face-54', + 78: 'face-55', + 79: 'face-56', + 80: 'face-57', + 81: 'face-58', + 82: 'face-59', + 83: 'face-60', + 84: 'face-61', + 85: 'face-62', + 86: 'face-63', + 87: 'face-64', + 88: 'face-65', + 89: 'face-66', + 90: 'face-67', + 91: 'left_hand_root', + 92: 'left_thumb1', + 93: 'left_thumb2', + 94: 'left_thumb3', + 95: 'left_thumb4', + 96: 'left_forefinger1', + 97: 'left_forefinger2', + 98: 'left_forefinger3', + 99: 'left_forefinger4', + 100: 'left_middle_finger1', + 101: 'left_middle_finger2', + 102: 'left_middle_finger3', + 103: 'left_middle_finger4', + 104: 'left_ring_finger1', + 105: 'left_ring_finger2', + 106: 'left_ring_finger3', + 107: 'left_ring_finger4', + 108: 'left_pinky_finger1', + 109: 'left_pinky_finger2', + 110: 'left_pinky_finger3', + 111: 'left_pinky_finger4', + 112: 'right_hand_root', + 113: 'right_thumb1', + 114: 'right_thumb2', + 115: 'right_thumb3', + 116: 'right_thumb4', + 117: 'right_forefinger1', + 118: 'right_forefinger2', + 119: 'right_forefinger3', + 120: 'right_forefinger4', + 121: 'right_middle_finger1', + 122: 'right_middle_finger2', + 123: 'right_middle_finger3', + 124: 'right_middle_finger4', + 125: 'right_ring_finger1', + 126: 'right_ring_finger2', + 127: 'right_ring_finger3', + 128: 'right_ring_finger4', + 129: 'right_pinky_finger1', + 130: 'right_pinky_finger2', + 131: 'right_pinky_finger3', + 132: 'right_pinky_finger4' + }, + 'skeleton': [ + [15, 13], [13, 11], [16, 14], [14, 12], [11, 12], [5, 11], [6, 12], + [5, 6], [5, 7], [6, 8], [7, 9], [8, 10], [1, 2], [0, 1], [0, 2], + [1, 3], [2, 4], [3, 5], [4, 6], [15, 17], [15, 18], [15, 19], + [16, 20], [16, 21], [16, 22], [91, 92], [92, 93], [93, 94], + [94, 95], [91, 96], [96, 97], [97, 98], [98, 99], [91, 100], + [100, 101], [101, 102], [102, 103], [91, 104], [104, 105], + [105, 106], [106, 107], [91, 108], [108, 109], [109, 110], + [110, 111], [112, 113], [113, 114], [114, 115], [115, 116], + [112, 117], [117, 118], [118, 119], [119, 120], [112, 121], + [121, 122], [122, 123], [123, 124], [112, 125], [125, 126], + [126, 127], [127, 128], [112, 129], [129, 130], [130, 131], + [131, 132] + ] + } + } + return joints + + +def draw_points(image, points, color_palette='tab20', palette_samples=16, confidence_threshold=0.5): + """ + Draws `points` on `image`. + + Args: + image: image in opencv format + points: list of points to be drawn. + Shape: (nof_points, 3) + Format: each point should contain (y, x, confidence) + color_palette: name of a matplotlib color palette + Default: 'tab20' + palette_samples: number of different colors sampled from the `color_palette` + Default: 16 + confidence_threshold: only points with a confidence higher than this threshold will be drawn. Range: [0, 1] + Default: 0.5 + + Returns: + A new image with overlaid points + + """ + try: + colors = np.round( + np.array(plt.get_cmap(color_palette).colors) * 255 + ).astype(np.uint8)[:, ::-1].tolist() + except AttributeError: # if palette has not pre-defined colors + colors = np.round( + np.array(plt.get_cmap(color_palette)(np.linspace(0, 1, palette_samples))) * 255 + ).astype(np.uint8)[:, -2::-1].tolist() + + circle_size = max(1, min(image.shape[:2]) // 150) # ToDo Shape it taking into account the size of the detection + # circle_size = max(2, int(np.sqrt(np.max(np.max(points, axis=0) - np.min(points, axis=0)) // 16))) + + for i, pt in enumerate(points): + if pt[2] > confidence_threshold: + image = cv2.circle(image, (int(pt[1]), int(pt[0])), circle_size, tuple(colors[i % len(colors)]), -1) + + return image + + +def draw_skeleton(image, points, skeleton, color_palette='Set2', palette_samples=8, person_index=0, + confidence_threshold=0.5): + """ + Draws a `skeleton` on `image`. + + Args: + image: image in opencv format + points: list of points to be drawn. + Shape: (nof_points, 3) + Format: each point should contain (y, x, confidence) + skeleton: list of joints to be drawn + Shape: (nof_joints, 2) + Format: each joint should contain (point_a, point_b) where `point_a` and `point_b` are an index in `points` + color_palette: name of a matplotlib color palette + Default: 'Set2' + palette_samples: number of different colors sampled from the `color_palette` + Default: 8 + person_index: index of the person in `image` + Default: 0 + confidence_threshold: only points with a confidence higher than this threshold will be drawn. Range: [0, 1] + Default: 0.5 + + Returns: + A new image with overlaid joints + + """ + try: + colors = np.round( + np.array(plt.get_cmap(color_palette).colors) * 255 + ).astype(np.uint8)[:, ::-1].tolist() + except AttributeError: # if palette has not pre-defined colors + colors = np.round( + np.array(plt.get_cmap(color_palette)(np.linspace(0, 1, palette_samples))) * 255 + ).astype(np.uint8)[:, -2::-1].tolist() + + for i, joint in enumerate(skeleton): + pt1, pt2 = points[joint] + if pt1[2] > confidence_threshold and pt2[2] > confidence_threshold: + image = cv2.line( + image, (int(pt1[1]), int(pt1[0])), (int(pt2[1]), int(pt2[0])), + tuple(colors[person_index % len(colors)]), 2 + ) + + return image + + +def draw_points_and_skeleton(image, points, skeleton, points_color_palette='tab20', points_palette_samples=16, + skeleton_color_palette='Set2', skeleton_palette_samples=8, person_index=0, + confidence_threshold=0.5): + """ + Draws `points` and `skeleton` on `image`. + + Args: + image: image in opencv format + points: list of points to be drawn. + Shape: (nof_points, 3) + Format: each point should contain (y, x, confidence) + skeleton: list of joints to be drawn + Shape: (nof_joints, 2) + Format: each joint should contain (point_a, point_b) where `point_a` and `point_b` are an index in `points` + points_color_palette: name of a matplotlib color palette + Default: 'tab20' + points_palette_samples: number of different colors sampled from the `color_palette` + Default: 16 + skeleton_color_palette: name of a matplotlib color palette + Default: 'Set2' + skeleton_palette_samples: number of different colors sampled from the `color_palette` + Default: 8 + person_index: index of the person in `image` + Default: 0 + confidence_threshold: only points with a confidence higher than this threshold will be drawn. Range: [0, 1] + Default: 0.5 + + Returns: + A new image with overlaid joints + + """ + image = draw_skeleton(image, points, skeleton, color_palette=skeleton_color_palette, + palette_samples=skeleton_palette_samples, person_index=person_index, + confidence_threshold=confidence_threshold) + image = draw_points(image, points, color_palette=points_color_palette, palette_samples=points_palette_samples, + confidence_threshold=confidence_threshold) + return image + + +def save_images(images, target, joint_target, output, joint_output, joint_visibility, summary_writer=None, step=0, + prefix=''): + """ + Creates a grid of images with gt joints and a grid with predicted joints. + This is a basic function for debugging purposes only. + + If summary_writer is not None, the grid will be written in that SummaryWriter with name "{prefix}_images" and + "{prefix}_predictions". + + Args: + images (torch.Tensor): a tensor of images with shape (batch x channels x height x width). + target (torch.Tensor): a tensor of gt heatmaps with shape (batch x channels x height x width). + joint_target (torch.Tensor): a tensor of gt joints with shape (batch x joints x 2). + output (torch.Tensor): a tensor of predicted heatmaps with shape (batch x channels x height x width). + joint_output (torch.Tensor): a tensor of predicted joints with shape (batch x joints x 2). + joint_visibility (torch.Tensor): a tensor of joint visibility with shape (batch x joints). + summary_writer (tb.SummaryWriter): a SummaryWriter where write the grids. + Default: None + step (int): summary_writer step. + Default: 0 + prefix (str): summary_writer name prefix. + Default: "" + + Returns: + A pair of images which are built from torchvision.utils.make_grid + """ + # Input images with gt + images_ok = images.detach().clone() + images_ok[:, 0].mul_(0.229).add_(0.485) + images_ok[:, 1].mul_(0.224).add_(0.456) + images_ok[:, 2].mul_(0.225).add_(0.406) + for i in range(images.shape[0]): + joints = joint_target[i] * 4. + joints_vis = joint_visibility[i] + + for joint, joint_vis in zip(joints, joints_vis): + if joint_vis[0]: + a = int(joint[1].item()) + b = int(joint[0].item()) + # images_ok[i][:, a-1:a+1, b-1:b+1] = torch.tensor([1, 0, 0]) + images_ok[i][0, a - 1:a + 1, b - 1:b + 1] = 1 + images_ok[i][1:, a - 1:a + 1, b - 1:b + 1] = 0 + grid_gt = torchvision.utils.make_grid(images_ok, nrow=int(images_ok.shape[0] ** 0.5), padding=2, normalize=False) + if summary_writer is not None: + summary_writer.add_image(prefix + 'images', grid_gt, global_step=step) + + # Input images with prediction + images_ok = images.detach().clone() + images_ok[:, 0].mul_(0.229).add_(0.485) + images_ok[:, 1].mul_(0.224).add_(0.456) + images_ok[:, 2].mul_(0.225).add_(0.406) + for i in range(images.shape[0]): + joints = joint_output[i] * 4. + joints_vis = joint_visibility[i] + + for joint, joint_vis in zip(joints, joints_vis): + if joint_vis[0]: + a = int(joint[1].item()) + b = int(joint[0].item()) + # images_ok[i][:, a-1:a+1, b-1:b+1] = torch.tensor([1, 0, 0]) + images_ok[i][0, a - 1:a + 1, b - 1:b + 1] = 1 + images_ok[i][1:, a - 1:a + 1, b - 1:b + 1] = 0 + grid_pred = torchvision.utils.make_grid(images_ok, nrow=int(images_ok.shape[0] ** 0.5), padding=2, normalize=False) + if summary_writer is not None: + summary_writer.add_image(prefix + 'predictions', grid_pred, global_step=step) + + # Heatmaps + # ToDo + # for h in range(0,17): + # heatmap = torchvision.utils.make_grid(output[h].detach(), nrow=int(np.sqrt(output.shape[0])), + # padding=2, normalize=True, range=(0, 1)) + # summary_writer.add_image('train_heatmap_%d' % h, heatmap, global_step=step + epoch*len_dl_train) + + return grid_gt, grid_pred + + +def check_video_rotation(filename): + # thanks to + # https://stackoverflow.com/questions/53097092/frame-from-video-is-upside-down-after-extracting/55747773#55747773 + + # this returns meta-data of the video file in form of a dictionary + meta_dict = ffmpeg.probe(filename) + + # from the dictionary, meta_dict['streams'][0]['tags']['rotate'] is the key + # we are looking for + rotation_code = None + try: + if int(meta_dict['streams'][0]['tags']['rotate']) == 90: + rotation_code = cv2.ROTATE_90_CLOCKWISE + elif int(meta_dict['streams'][0]['tags']['rotate']) == 180: + rotation_code = cv2.ROTATE_180 + elif int(meta_dict['streams'][0]['tags']['rotate']) == 270: + rotation_code = cv2.ROTATE_90_COUNTERCLOCKWISE + else: + raise ValueError + except KeyError: + pass + + return rotation_code diff --git a/main_func.py b/main_func.py new file mode 100644 index 0000000000000000000000000000000000000000..35848be298d07e1c1d14d6f5c0254c5769ea20d8 --- /dev/null +++ b/main_func.py @@ -0,0 +1,169 @@ +from utils import ( + predict_keypoints_vitpose, + get_edge_groups, + get_series, + z_score_normalization, + modify_student_frame, + modify_student_frame_2, + get_video_frames, + check_and_download_models +) + +from config import ( + CONNECTIONS_VIT_FULL, + CONNECTIONS_FOR_ERROR, + EDGE_GROUPS_FOR_ERRORS, + EDGE_GROUPS_FOR_SUMMARY, + get_thresholds +) + +from dtaidistance import dtw +import numpy as np +from scipy.signal import savgol_filter +from scipy.stats import mstats +from datetime import timedelta +import cv2 + + +def video_identity(dtw_mean, dtw_filter, angles_sensitive, angles_common, angles_insensitive, trigger_state, video_teacher, video_student): + + check_and_download_models() + + detection_result_teacher = predict_keypoints_vitpose( + video_path=video_teacher, + model_path="models/vitpose-l-wholebody.pth", + model_name="l", + detector_path="models/yolov8s.pt" + ) + + detection_result_student = predict_keypoints_vitpose( + video_path=video_student, + model_path="models/vitpose-l-wholebody.pth", + model_name="l", + detector_path="models/yolov8s.pt" + ) + + detection_result_teacher_angles = get_series(detection_result_teacher[:, :,:-1], EDGE_GROUPS_FOR_ERRORS).T + detection_result_student_angles = get_series(detection_result_student[:, :,:-1], EDGE_GROUPS_FOR_ERRORS).T + + + edge_groups_for_dtw = get_edge_groups(CONNECTIONS_VIT_FULL) + serieses_teacher = get_series(detection_result_teacher[:, :,:-1], edge_groups_for_dtw) + serieses_student = get_series(detection_result_student[:, :,:-1], edge_groups_for_dtw) + + serieses_teacher = z_score_normalization(serieses_teacher) + serieses_student = z_score_normalization(serieses_student) + + list_of_paths = [] + for idx in range(len(serieses_teacher)): + series_teacher = np.array(serieses_teacher[idx]) + series_student = np.array(serieses_student[idx]) + _ , paths = dtw.warping_paths(series_teacher, series_student, window=50) + path = dtw.best_path(paths) + + list_of_paths.append(path) + + + all_dtw_tupples = [] + for path in list_of_paths: + all_dtw_tupples.extend(path) + + mean_path = [] + for student_frame in range(len(serieses_student[0])): + frame_from_teacher = [] + for frame_teacher in all_dtw_tupples: + if frame_teacher[1] == student_frame: + frame_from_teacher.append(frame_teacher[0]) + + mean_path.append((int(mstats.winsorize(np.array(frame_from_teacher), limits=[dtw_mean, dtw_mean]).mean()), student_frame)) + + path_array = np.array(mean_path) + smoothed_data = savgol_filter(path_array, window_length=dtw_filter, polyorder=0, axis=0) + path_array = np.array(smoothed_data).astype(int) + + video_teacher_loaded = get_video_frames(video_teacher) + video_student_loaded = get_video_frames(video_student) + + alignments = np.unique(path_array, axis=0) + + threshouds_for_errors = get_thresholds(angles_sensitive, angles_common, angles_insensitive) + +# ====================================================================================== + + trigger_1 = [] + trigger_2 = [] + + save_teacher_frames = [] + save_student_frames = [] + all_text_summaries = [] + for idx, alignment in enumerate(alignments): + + frame_student_out, frame_teacher_out, trigger_1, trigger_2, text_info_summary = modify_student_frame( + detection_result_student=detection_result_student, + + detection_result_teacher_angles=detection_result_teacher_angles, + detection_result_student_angles=detection_result_student_angles, + + video_teacher=video_teacher_loaded, + video_student=video_student_loaded, + + alignment_frames=alignment, + + edge_groups=EDGE_GROUPS_FOR_ERRORS, + connections=CONNECTIONS_FOR_ERROR, + thresholds=threshouds_for_errors, + previously_trigered=trigger_1, + previously_trigered_2=trigger_2, + triger_state=trigger_state, + text_dictionary=EDGE_GROUPS_FOR_SUMMARY + ) + + save_teacher_frames.append(frame_teacher_out) + save_student_frames.append(frame_student_out) + + text_info_summary = [(log, idx) for log in text_info_summary] + all_text_summaries.extend(text_info_summary) + + + + + save_teacher_frames = np.array(save_teacher_frames) + save_student_frames = np.array(save_student_frames) + + save_teacher_frames_resized = np.array([cv2.resize(frame, (1280, 720)) for frame in save_teacher_frames]) + save_student_frames_resized = np.array([cv2.resize(frame, (1280, 720)) for frame in save_student_frames]) + + # print(f"video shape: {save_student_frames.shape}") + + print(f"shape s: {save_student_frames.shape}") + print(f"shape t: {save_teacher_frames.shape}") + + concat_video = [] + # print(alignments) + + + concat_video = np.concatenate((save_teacher_frames_resized, save_student_frames_resized), axis=2) + + concat_video = np.array(concat_video) + + out = cv2.VideoWriter("videos/concat_modified.mp4", cv2.VideoWriter_fourcc(*'mp4v'), 30, (1280*2, 720)) + for frame in concat_video: + out.write(frame) + out.release() + + + all_text_summaries_clean = list(set(all_text_summaries)) + all_text_summaries_clean.sort(key=lambda x: x[1]) + + general_summary = [] + + for log in all_text_summaries_clean: + comment, frame = log + + total_seconds = frame / 30 + + general_summary.append(f"{comment} on frame {frame}. Video time: {str(timedelta(seconds=total_seconds))[3:-4]}") + + general_summary = "\n".join(general_summary) + + return "videos/concat_modified.mp4", general_summary \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc4da99d2f4197e05f197947ff9f35f51b5814e5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,55 @@ +torch>=2.0 +gradio==4.36.1 +dtaidistance==2.3.12 +open3d==0.18.0 +plotly==5.22.0 +certifi==2023.7.22 +charset-normalizer==3.2.0 +coloredlogs==15.0.1 +contourpy==1.1.1 +cycler==0.11.0 +ffmpeg==1.4 +filelock==3.12.4 +filterpy==1.4.5 +flatbuffers==23.5.26 +fonttools==4.43.0 +humanfriendly==10.0 +idna==3.4 +imageio==2.31.3 +importlib-resources==6.1.0 +jinja2>=3.1.3 +kiwisolver==1.4.5 +lazy_loader==0.3 +MarkupSafe==2.1.3 +matplotlib==3.8.0 +mpmath==1.3.0 +networkx==3.1 +numpy==1.26.0 +onnx==1.14.1 +onnxruntime==1.16.0 +opencv-python==4.8.0.76 +packaging==23.1 +pandas==2.1.1 +Pillow>=10.2.0 +protobuf==4.24.3 +psutil==5.9.5 +py-cpuinfo==9.0.0 +pyparsing==3.1.1 +python-dateutil==2.8.2 +pytz==2023.3.post1 +PyWavelets==1.4.1 +PyYAML==6.0.1 +requests==2.31.0 +scikit-image==0.21.0 +scipy==1.11.2 +seaborn==0.12.2 +six==1.16.0 +sympy==1.12 +tifffile==2023.9.18 +tqdm==4.66.1 +typing_extensions==4.8.0 +tzdata==2023.3 +ultralytics==8.0.184 +urllib3>=2.0.7 +zipp==3.17.0 +openpyxl==3.1.4 \ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..ac1965c04addd2040b43f27486632ff433971400 --- /dev/null +++ b/utils.py @@ -0,0 +1,415 @@ +import cv2 +import numpy as np +import matplotlib.pyplot as plt +from dtaidistance import dtw +from easy_ViTPose.inference import VitInference +import os +import requests +from pathlib import Path + + +def predict_keypoints_vitpose( + video_path, + model_path, + model_name, + detector_path, + display_video=False +): + + model = VitInference( + model=model_path, + yolo=detector_path, + model_name=model_name, + det_class=None, + dataset=None, + yolo_size=320, + is_video=False, + single_pose=False, + yolo_step=1 + ) + + cap = cv2.VideoCapture(video_path) + detection_results = [] + while True: + ret, frame = cap.read() + if not ret: + print("End") + break + + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + frame_keypoints = model.inference(frame) + + if 0 in frame_keypoints: + detection_results.append(frame_keypoints[0]) + + if display_video: + frame = model.draw(False, False, 0.5)[..., ::-1] + + if display_video: + cv2.imshow('preview', frame) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + if display_video: + cap.release() + cv2.destroyAllWindows() + + return np.array(detection_results) + + +def get_point_list_vitpose(detection_results): + return np.array(detection_results)[:, :, :-1] + + +def get_edge_groups(connections): + + all_pairs = [] + for i in range(len(connections)): + pairs = [] + + init_con = connections[i] + for k in range(len(connections)): + if k == i: + pass + candidat_con = connections[k] + + point_1_init, point_2_init = init_con + point_1_candidat, point_2_candidat = candidat_con + + if point_1_candidat == point_1_init or point_1_candidat == point_2_init or point_2_candidat == point_1_init or point_2_candidat == point_2_init: + pairs.append([init_con, candidat_con]) + all_pairs.append(pairs) + + all_point_for_edges = [] + for set_of_pairs in all_pairs: + clean_pairs = [] + for pair in set_of_pairs: + pair_a = pair[0] + pair_b = pair[1] + if len(list(set(pair_a + pair_b))) == 3: + + center = int(list(set(pair_a) & set(pair_b))[0]) + edges = list(set(pair_a) ^ set(pair_b)) + points_for_edge = [edges[0], center, edges[1]] + clean_pairs.append(points_for_edge) + all_point_for_edges.extend(clean_pairs) + + + unique_set = set() + unique_list = [] + + for sublist in all_point_for_edges: + sublist_tuple = tuple(sublist) + if sublist_tuple not in unique_set: + unique_set.add(sublist_tuple) + unique_list.append(sublist) + + unique_list.sort() + + return unique_list + + +def calculate_angle(A, B, C): + """ + Calculate the angle at point B formed by the line segments AB and BC, + and the minimum length of these segments. + + Parameters: + A Numpy array: Coordinates of point A (e.g., [x1, y1, z1]). + B Numpy array: Coordinates of point B (e.g., [x2, y2, z2]). + C Numpy array: Coordinates of point C (e.g., [x3, y3, z3]). + + Returns: + tuple: A tuple containing: + - angle (float): The angle at point B in degrees. + - minimum (float): The minimum length of the segments AB and BC. + """ + A = np.round(np.array(A), decimals=3) + B = np.round(np.array(B), decimals=3) + C = np.round(np.array(C), decimals=3) + + # Create vectors BA and BC + BA = A - B + BC = C - B + + # Compute the cosine of the angle using the dot product and magnitudes of BA and BC + cosine_angle = np.dot(BA, BC) / ((np.linalg.norm(BA) * np.linalg.norm(BC))+ 0.00001) + cosine_angle = np.clip(cosine_angle, -1, 1) + # Calculate the angle in radians and then convert to degrees + angle = np.arccos(cosine_angle) + + if np.isnan(angle): + print(f"Invalid angle calculation.\n{A} \n{B} \n{C}") + # Find the minimum length of the segments BA and BC + minimum = np.min(np.array((np.linalg.norm(BA), np.linalg.norm(BC)))) + + # Return the angle in degrees and the minimum segment length + return np.degrees(angle), minimum + + + +def compute_all_angels(keypoints, edge_groups): + all_angles = [] + for group in edge_groups: + + A = keypoints[group[0]] + B = keypoints[group[1]] + C = keypoints[group[2]] + + angle, minimum = calculate_angle(A, B, C) + all_angles.append([angle, minimum]) + + return np.array(all_angles) + + +def xy2phi(points_result, connections): + edge_groups = get_edge_groups(connections) + + + new_array = np.zeros((points_result.shape[0], len(edge_groups), 1)) + for idx, frame in enumerate(points_result): + all_angels = compute_all_angels(keypoints=frame, edge_groups=edge_groups)[:, 0] + new_array[idx, :, :] = all_angels.reshape((len(edge_groups), 1)) + + return new_array + + +def get_series(point_list, edge_groups): + + list_of_series = [] + + for edge_group in edge_groups: + keypoint_1, keypoint_2, keypoint_3 = edge_group + relevant_point_list = point_list[:, (keypoint_1, keypoint_2, keypoint_3), :] + + series = [] + for frame in relevant_point_list: + + angle, _ = calculate_angle(frame[0, :], frame[1, :], frame[2, :]) + + series.append(angle) + list_of_series.append(series) + + return np.array(list_of_series) + + +def plot_serieses(series_1, series_2): + plt.figure(dpi=150, figsize=(12, 5)) + plt.plot(series_1, label='Video #1: normal speed. 30 fps', lw=1) + plt.plot(series_2, label='Video #2: slowed(2X) / Croped. 30 fps', lw=1) + plt.axis("on") + plt.grid(True) + # plt.title("x-coordinate of the left elbow (keypoint 13) for two identical videos with different speeds but the same FPS") + plt.xlabel("frames") + plt.ylabel("mean of 72 angles") + plt.legend() + + +def z_score_normalization(serieses, axis_for_znorm=1): + + serieses_mean = np.mean(serieses, axis=axis_for_znorm, keepdims=True) + serieses_std = np.std(serieses, axis=axis_for_znorm, keepdims=True) + serieses_normalized = (serieses - serieses_mean) / serieses_std + + return serieses_normalized + + +def modify_student_frame_2( + detection_result_student, + detection_result_teacher_angles, + detection_result_student_angles, + video_teacher, + video_student, + alignment_frames, + edge_groups, + connections, + thresholds, + previously_trigered, + previously_trigered_2, + triger_state +): + frame_copy = video_student[alignment_frames[1]] + frame_teacher_copy = video_teacher[alignment_frames[0]] + + frame_errors = np.abs(detection_result_teacher_angles[alignment_frames[0]] - detection_result_student_angles[alignment_frames[1]]) + + edge_groups_as_keys = [tuple(group) for group in edge_groups] + edge_groups2errors = dict(zip(edge_groups_as_keys, frame_errors)) + edge_groups2thresholds = dict(zip(edge_groups_as_keys, thresholds)) + edge_groups_relevant = [tuple(edge_group[1:]) for edge_group in edge_groups] + + trigered_connections = [] + trigered_connections2 = [] + + for connection in connections: + edges_for_given_connection = [edge for edge in edge_groups2errors if connection[0] in edge or connection[1] in edge] + + for edge in edges_for_given_connection: + if edge_groups2errors[edge] > edge_groups2thresholds[edge]: + if all(detection_result_student[alignment_frames[1], keypoint, -1] >= 0.7 for keypoint in edge): + if (connection[0], connection[1]) in edge_groups_relevant or (connection[1], connection[0]) in edge_groups_relevant: + point1 = detection_result_student[alignment_frames[1], connection[0], :2].astype(int) + point2 = detection_result_student[alignment_frames[1], connection[1], :2].astype(int) + point1, point2 = point1[::-1], point2[::-1] + + if triger_state == "three": + trigered_connections.append((connection[0], connection[1])) + if (connection[0], connection[1]) in previously_trigered: + trigered_connections2.append((connection[0], connection[1])) + if (connection[0], connection[1]) in previously_trigered_2: + cv2.line(frame_copy, tuple(point1), tuple(point2), (0, 0, 255), 5) + elif triger_state == "two": + trigered_connections.append((connection[0], connection[1])) + if (connection[0], connection[1]) in previously_trigered: + cv2.line(frame_copy, tuple(point1), tuple(point2), (0, 0, 255), 5) + + return frame_copy, frame_teacher_copy, list(set(trigered_connections)), list(set(trigered_connections2)) + + + +def modify_student_frame( + detection_result_student, + + detection_result_teacher_angles, + detection_result_student_angles, + + video_teacher, + video_student, + + alignment_frames, + + edge_groups, + connections, + thresholds, + previously_trigered, + previously_trigered_2, + triger_state, + text_dictionary, +): + + frame_copy = video_student[alignment_frames[1]] + frame_teacher_copy = video_teacher[alignment_frames[0]] + + frame_errors = np.abs(detection_result_teacher_angles[alignment_frames[0]] - detection_result_student_angles[alignment_frames[1]]) + + edge_groups_as_keys = [tuple(group) for group in edge_groups] + edge_groups2errors = dict(zip(edge_groups_as_keys, frame_errors)) + + edge_groups2thresholds = dict(zip(edge_groups_as_keys, thresholds)) + + edge_groups_relevant = [edge_group[1:] for edge_group in edge_groups] + + text_info = [] + trigered_connections = [] + trigered_connections2 = [] + + for connection in connections: + + # check every edge, that contain atleast one keypoint from connection + edges_for_given_connection = [edge for edge in edge_groups2errors if connection[0] in edge or connection[1] in edge] + + + for edge in edges_for_given_connection: + + # check if error in edge are grather then threshold for this edge + + + check_threshold = edge_groups2errors[edge] > edge_groups2thresholds[edge] + check_certain = True + for keypoint in edge: + prob = detection_result_student[:, :,-1][alignment_frames[1]][keypoint] + if prob < 0.7: + check_certain = False + + relevant_plane = [connection[0], connection[1]] in edge_groups_relevant or [connection[1], connection[0]] in edge_groups_relevant + + + if check_threshold and check_certain and relevant_plane: + + + + point1 = detection_result_student[:, :, :-1][alignment_frames[1]][connection[0]] + point2 = detection_result_student[:, :, :-1][alignment_frames[1]][connection[1]] + + point1 = np.array(point1).astype(int) + point2 = np.array(point2).astype(int) + + point1 = [point1[1], point1[0]] + point2 = [ point2[1], point2[0]] + + # print(f"trigger stats: {triger_state}") + + if triger_state == "three": + + trigered_connections.append((connection[0], connection[1])) + + if (connection[0], connection[1]) in previously_trigered: + + trigered_connections2.append((connection[0], connection[1])) + + if (connection[0], connection[1]) in previously_trigered_2: + + _ = cv2.line(frame_copy, point1, point2, (0, 0, 255), 10) + + if (connection[0], connection[1]) in text_dictionary: + text_info.append(text_dictionary[(connection[0], connection[1])]) + + if triger_state == "two": + + trigered_connections.append((connection[0], connection[1])) + + if (connection[0], connection[1]) in previously_trigered: + + _ = cv2.line(frame_copy, point1, point2, (0, 0, 255), 10) + + if (connection[0], connection[1]) in text_dictionary: + text_info.append(text_dictionary[(connection[0], connection[1])]) + + return frame_copy, frame_teacher_copy, list(set(trigered_connections)), list(set(trigered_connections2)), text_info + + +def get_video_frames(video_path): + cap = cv2.VideoCapture(video_path) + video = [] + while True: + ret, frame = cap.read() + if not ret: + print("End") + break + + # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + video.append(frame) + + return np.array(video) + + +def download_file(url, save_path): + response = requests.get(url, stream=True) + response.raise_for_status() + with open(save_path, 'wb') as file: + for chunk in response.iter_content(chunk_size=8192): + file.write(chunk) + +def check_and_download_models(): + + vit_model_url = "https://huggingface.co/JunkyByte/easy_ViTPose/resolve/main/torch/wholebody/vitpose-l-wholebody.pth?download=true" + yolo_model_url = "https://huggingface.co/JunkyByte/easy_ViTPose/resolve/main/yolov8/yolov8s.pt?download=true" + + vit_model_path = "models/vitpose-l-wholebody.pth" + + yolo_model_path = "models/yolov8s.pt" + + + Path(os.path.dirname(vit_model_path)).mkdir(parents=True, exist_ok=True) + Path(os.path.dirname(yolo_model_path)).mkdir(parents=True, exist_ok=True) + + + if not os.path.exists(vit_model_path): + print("Downloading ViT model...") + download_file(vit_model_url, vit_model_path) + + + if not os.path.exists(yolo_model_path): + print("Downloading YOLO model...") + download_file(yolo_model_url, yolo_model_path) \ No newline at end of file diff --git a/videos/text b/videos/text new file mode 100644 index 0000000000000000000000000000000000000000..8e27be7d6154a1f68ea9160ef0e18691d20560dc --- /dev/null +++ b/videos/text @@ -0,0 +1 @@ +text