summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r--src/gallium/auxiliary/Android.mk55
-rw-r--r--src/gallium/auxiliary/Makefile201
-rw-r--r--src/gallium/auxiliary/Makefile.sources200
-rw-r--r--src/gallium/auxiliary/SConscript205
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c48
-rw-r--r--src/gallium/auxiliary/gallivm/f.cpp23
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c36
-rw-r--r--src/gallium/auxiliary/os/os_mman.h87
-rw-r--r--src/gallium/auxiliary/os/os_thread.h2
-rw-r--r--src/gallium/auxiliary/postprocess/ADDING87
-rw-r--r--src/gallium/auxiliary/postprocess/filters.h58
-rw-r--r--src/gallium/auxiliary/postprocess/postprocess.h100
-rw-r--r--src/gallium/auxiliary/postprocess/pp_celshade.c38
-rw-r--r--src/gallium/auxiliary/postprocess/pp_celshade.h79
-rw-r--r--src/gallium/auxiliary/postprocess/pp_colors.c80
-rw-r--r--src/gallium/auxiliary/postprocess/pp_colors.h69
-rw-r--r--src/gallium/auxiliary/postprocess/pp_filters.h57
-rw-r--r--src/gallium/auxiliary/postprocess/pp_init.c283
-rw-r--r--src/gallium/auxiliary/postprocess/pp_mlaa.c304
-rw-r--r--src/gallium/auxiliary/postprocess/pp_mlaa.h342
-rw-r--r--src/gallium/auxiliary/postprocess/pp_mlaa_areamap.h2821
-rw-r--r--src/gallium/auxiliary/postprocess/pp_program.c139
-rw-r--r--src/gallium/auxiliary/postprocess/pp_program.h64
-rw-r--r--src/gallium/auxiliary/postprocess/pp_run.c188
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c100
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.h7
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_scan.c38
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_scan.h3
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c45
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h21
-rw-r--r--src/gallium/auxiliary/util/u_debug.c2
-rw-r--r--src/gallium/auxiliary/util/u_format.c50
-rw-r--r--src/gallium/auxiliary/util/u_format.csv14
-rw-r--r--src/gallium/auxiliary/util/u_format.h19
-rw-r--r--src/gallium/auxiliary/util/u_format_s3tc.c11
-rw-r--r--src/gallium/auxiliary/util/u_math.h12
-rw-r--r--src/gallium/auxiliary/util/u_pstipple.c43
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.c56
-rw-r--r--src/gallium/auxiliary/util/u_vbuf_mgr.h17
-rw-r--r--src/gallium/auxiliary/vl/vl_compositor.c26
-rw-r--r--src/gallium/auxiliary/vl/vl_compositor.h2
-rw-r--r--src/gallium/auxiliary/vl/vl_decoder.c13
-rw-r--r--src/gallium/auxiliary/vl/vl_decoder.h6
-rw-r--r--src/gallium/auxiliary/vl/vl_idct.c3
-rw-r--r--src/gallium/auxiliary/vl/vl_mc.c6
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c2439
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_bitstream.h21
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_decoder.c705
-rw-r--r--src/gallium/auxiliary/vl/vl_mpeg12_decoder.h23
-rw-r--r--src/gallium/auxiliary/vl/vl_vertex_buffers.c61
-rw-r--r--src/gallium/auxiliary/vl/vl_vertex_buffers.h54
-rw-r--r--src/gallium/auxiliary/vl/vl_vlc.h202
52 files changed, 6977 insertions, 2588 deletions
diff --git a/src/gallium/auxiliary/Android.mk b/src/gallium/auxiliary/Android.mk
new file mode 100644
index 00000000000..0c37dd31ab6
--- /dev/null
+++ b/src/gallium/auxiliary/Android.mk
@@ -0,0 +1,55 @@
+# Mesa 3-D graphics library
+#
+# Copyright (C) 2010-2011 Chia-I Wu <[email protected]>
+# Copyright (C) 2010-2011 LunarG Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+LOCAL_PATH := $(call my-dir)
+
+# get C_SOURCES and GENERATED_SOURCES
+include $(LOCAL_PATH)/Makefile.sources
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(C_SOURCES)
+
+LOCAL_C_INCLUDES := $(GALLIUM_TOP)/auxiliary/util
+
+LOCAL_MODULE := libmesa_gallium
+
+# generate sources
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+intermediates := $(call local-intermediates-dir)
+LOCAL_GENERATED_SOURCES := $(addprefix $(intermediates)/, $(GENERATED_SOURCES))
+
+$(LOCAL_GENERATED_SOURCES): PRIVATE_PYTHON := $(MESA_PYTHON2)
+$(LOCAL_GENERATED_SOURCES): PRIVATE_CUSTOM_TOOL = $(PRIVATE_PYTHON) $^ > $@
+
+$(intermediates)/indices/u_indices_gen.c \
+$(intermediates)/indices/u_unfilled_gen.c \
+$(intermediates)/util/u_format_srgb.c \
+$(intermediates)/util/u_half.c: $(intermediates)/%.c: $(LOCAL_PATH)/%.py
+ $(transform-generated-source)
+
+$(intermediates)/util/u_format_table.c: $(intermediates)/%.c: $(LOCAL_PATH)/%.py $(LOCAL_PATH)/util/u_format.csv
+ $(transform-generated-source)
+
+include $(GALLIUM_COMMON_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index 7dae7bc908b..896c058fde9 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -3,205 +3,10 @@ include $(TOP)/configs/current
LIBNAME = gallium
-C_SOURCES = \
- cso_cache/cso_cache.c \
- cso_cache/cso_context.c \
- cso_cache/cso_hash.c \
- draw/draw_context.c \
- draw/draw_fs.c \
- draw/draw_gs.c \
- draw/draw_pipe.c \
- draw/draw_pipe_aaline.c \
- draw/draw_pipe_aapoint.c \
- draw/draw_pipe_clip.c \
- draw/draw_pipe_cull.c \
- draw/draw_pipe_flatshade.c \
- draw/draw_pipe_offset.c \
- draw/draw_pipe_pstipple.c \
- draw/draw_pipe_stipple.c \
- draw/draw_pipe_twoside.c \
- draw/draw_pipe_unfilled.c \
- draw/draw_pipe_util.c \
- draw/draw_pipe_validate.c \
- draw/draw_pipe_vbuf.c \
- draw/draw_pipe_wide_line.c \
- draw/draw_pipe_wide_point.c \
- draw/draw_pt.c \
- draw/draw_pt_emit.c \
- draw/draw_pt_fetch.c \
- draw/draw_pt_fetch_emit.c \
- draw/draw_pt_fetch_shade_emit.c \
- draw/draw_pt_fetch_shade_pipeline.c \
- draw/draw_pt_post_vs.c \
- draw/draw_pt_so_emit.c \
- draw/draw_pt_util.c \
- draw/draw_pt_vsplit.c \
- draw/draw_vertex.c \
- draw/draw_vs.c \
- draw/draw_vs_aos.c \
- draw/draw_vs_aos_io.c \
- draw/draw_vs_aos_machine.c \
- draw/draw_vs_exec.c \
- draw/draw_vs_ppc.c \
- draw/draw_vs_sse.c \
- draw/draw_vs_variant.c \
- indices/u_indices_gen.c \
- indices/u_unfilled_gen.c \
- os/os_misc.c \
- os/os_stream.c \
- os/os_stream_log.c \
- os/os_stream_null.c \
- os/os_stream_stdc.c \
- os/os_stream_str.c \
- os/os_time.c \
- pipebuffer/pb_buffer_fenced.c \
- pipebuffer/pb_buffer_malloc.c \
- pipebuffer/pb_bufmgr_alt.c \
- pipebuffer/pb_bufmgr_cache.c \
- pipebuffer/pb_bufmgr_debug.c \
- pipebuffer/pb_bufmgr_mm.c \
- pipebuffer/pb_bufmgr_ondemand.c \
- pipebuffer/pb_bufmgr_pool.c \
- pipebuffer/pb_bufmgr_slab.c \
- pipebuffer/pb_validate.c \
- rbug/rbug_connection.c \
- rbug/rbug_context.c \
- rbug/rbug_core.c \
- rbug/rbug_demarshal.c \
- rbug/rbug_texture.c \
- rbug/rbug_shader.c \
- rtasm/rtasm_cpu.c \
- rtasm/rtasm_execmem.c \
- rtasm/rtasm_ppc.c \
- rtasm/rtasm_ppc_spe.c \
- rtasm/rtasm_x86sse.c \
- tgsi/tgsi_build.c \
- tgsi/tgsi_dump.c \
- tgsi/tgsi_exec.c \
- tgsi/tgsi_info.c \
- tgsi/tgsi_iterate.c \
- tgsi/tgsi_parse.c \
- tgsi/tgsi_ppc.c \
- tgsi/tgsi_sanity.c \
- tgsi/tgsi_scan.c \
- tgsi/tgsi_sse2.c \
- tgsi/tgsi_text.c \
- tgsi/tgsi_transform.c \
- tgsi/tgsi_ureg.c \
- tgsi/tgsi_util.c \
- translate/translate.c \
- translate/translate_cache.c \
- translate/translate_generic.c \
- translate/translate_sse.c \
- util/u_debug.c \
- util/u_debug_describe.c \
- util/u_debug_refcnt.c \
- util/u_debug_stack.c \
- util/u_debug_symbol.c \
- util/u_dump_defines.c \
- util/u_dump_state.c \
- util/u_bitmask.c \
- util/u_blit.c \
- util/u_blitter.c \
- util/u_cache.c \
- util/u_caps.c \
- util/u_cpu_detect.c \
- util/u_dl.c \
- util/u_draw.c \
- util/u_draw_quad.c \
- util/u_format.c \
- util/u_format_other.c \
- util/u_format_latc.c \
- util/u_format_s3tc.c \
- util/u_format_rgtc.c \
- util/u_format_srgb.c \
- util/u_format_table.c \
- util/u_format_tests.c \
- util/u_format_yuv.c \
- util/u_format_zs.c \
- util/u_framebuffer.c \
- util/u_gen_mipmap.c \
- util/u_half.c \
- util/u_handle_table.c \
- util/u_hash.c \
- util/u_hash_table.c \
- util/u_index_modify.c \
- util/u_keymap.c \
- util/u_linear.c \
- util/u_linkage.c \
- util/u_network.c \
- util/u_math.c \
- util/u_mm.c \
- util/u_pstipple.c \
- util/u_rect.c \
- util/u_ringbuffer.c \
- util/u_sampler.c \
- util/u_simple_shaders.c \
- util/u_slab.c \
- util/u_snprintf.c \
- util/u_staging.c \
- util/u_surface.c \
- util/u_surfaces.c \
- util/u_texture.c \
- util/u_tile.c \
- util/u_transfer.c \
- util/u_resource.c \
- util/u_upload_mgr.c \
- util/u_vbuf_mgr.c \
- vl/vl_csc.c \
- vl/vl_compositor.c \
- vl/vl_decoder.c \
- vl/vl_mpeg12_decoder.c \
- vl/vl_mpeg12_bitstream.c \
- vl/vl_zscan.c \
- vl/vl_idct.c \
- vl/vl_mc.c \
- vl/vl_vertex_buffers.c \
- vl/vl_video_buffer.c
-
-GALLIVM_SOURCES = \
- gallivm/lp_bld_arit.c \
- gallivm/lp_bld_assert.c \
- gallivm/lp_bld_bitarit.c \
- gallivm/lp_bld_const.c \
- gallivm/lp_bld_conv.c \
- gallivm/lp_bld_flow.c \
- gallivm/lp_bld_format_aos.c \
- gallivm/lp_bld_format_soa.c \
- gallivm/lp_bld_format_yuv.c \
- gallivm/lp_bld_gather.c \
- gallivm/lp_bld_init.c \
- gallivm/lp_bld_intr.c \
- gallivm/lp_bld_logic.c \
- gallivm/lp_bld_pack.c \
- gallivm/lp_bld_printf.c \
- gallivm/lp_bld_quad.c \
- gallivm/lp_bld_sample.c \
- gallivm/lp_bld_sample_aos.c \
- gallivm/lp_bld_sample_soa.c \
- gallivm/lp_bld_struct.c \
- gallivm/lp_bld_swizzle.c \
- gallivm/lp_bld_tgsi_aos.c \
- gallivm/lp_bld_tgsi_info.c \
- gallivm/lp_bld_tgsi_soa.c \
- gallivm/lp_bld_type.c \
- draw/draw_llvm.c \
- draw/draw_llvm_sample.c \
- draw/draw_llvm_translate.c \
- draw/draw_vs_llvm.c \
- draw/draw_pt_fetch_shade_pipeline_llvm.c
-
-GALLIVM_CPP_SOURCES = \
- gallivm/lp_bld_debug.cpp \
- gallivm/lp_bld_misc.cpp
-
-GENERATED_SOURCES = \
- indices/u_indices_gen.c \
- indices/u_unfilled_gen.c \
- util/u_format_srgb.c \
- util/u_format_table.c \
- util/u_half.c
+# get source lists
+include Makefile.sources
+C_SOURCES += $(GENERATED_SOURCES)
ifeq ($(MESA_LLVM),1)
C_SOURCES += \
diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources
new file mode 100644
index 00000000000..766beb0fafc
--- /dev/null
+++ b/src/gallium/auxiliary/Makefile.sources
@@ -0,0 +1,200 @@
+C_SOURCES := \
+ cso_cache/cso_cache.c \
+ cso_cache/cso_context.c \
+ cso_cache/cso_hash.c \
+ draw/draw_context.c \
+ draw/draw_fs.c \
+ draw/draw_gs.c \
+ draw/draw_pipe.c \
+ draw/draw_pipe_aaline.c \
+ draw/draw_pipe_aapoint.c \
+ draw/draw_pipe_clip.c \
+ draw/draw_pipe_cull.c \
+ draw/draw_pipe_flatshade.c \
+ draw/draw_pipe_offset.c \
+ draw/draw_pipe_pstipple.c \
+ draw/draw_pipe_stipple.c \
+ draw/draw_pipe_twoside.c \
+ draw/draw_pipe_unfilled.c \
+ draw/draw_pipe_util.c \
+ draw/draw_pipe_validate.c \
+ draw/draw_pipe_vbuf.c \
+ draw/draw_pipe_wide_line.c \
+ draw/draw_pipe_wide_point.c \
+ draw/draw_pt.c \
+ draw/draw_pt_emit.c \
+ draw/draw_pt_fetch.c \
+ draw/draw_pt_fetch_emit.c \
+ draw/draw_pt_fetch_shade_emit.c \
+ draw/draw_pt_fetch_shade_pipeline.c \
+ draw/draw_pt_post_vs.c \
+ draw/draw_pt_so_emit.c \
+ draw/draw_pt_util.c \
+ draw/draw_pt_vsplit.c \
+ draw/draw_vertex.c \
+ draw/draw_vs.c \
+ draw/draw_vs_aos.c \
+ draw/draw_vs_aos_io.c \
+ draw/draw_vs_aos_machine.c \
+ draw/draw_vs_exec.c \
+ draw/draw_vs_ppc.c \
+ draw/draw_vs_sse.c \
+ draw/draw_vs_variant.c \
+ os/os_misc.c \
+ os/os_stream.c \
+ os/os_stream_log.c \
+ os/os_stream_null.c \
+ os/os_stream_stdc.c \
+ os/os_stream_str.c \
+ os/os_time.c \
+ pipebuffer/pb_buffer_fenced.c \
+ pipebuffer/pb_buffer_malloc.c \
+ pipebuffer/pb_bufmgr_alt.c \
+ pipebuffer/pb_bufmgr_cache.c \
+ pipebuffer/pb_bufmgr_debug.c \
+ pipebuffer/pb_bufmgr_mm.c \
+ pipebuffer/pb_bufmgr_ondemand.c \
+ pipebuffer/pb_bufmgr_pool.c \
+ pipebuffer/pb_bufmgr_slab.c \
+ pipebuffer/pb_validate.c \
+ postprocess/pp_celshade.c \
+ postprocess/pp_colors.c \
+ postprocess/pp_init.c \
+ postprocess/pp_mlaa.c \
+ postprocess/pp_run.c \
+ postprocess/pp_program.c \
+ rbug/rbug_connection.c \
+ rbug/rbug_context.c \
+ rbug/rbug_core.c \
+ rbug/rbug_demarshal.c \
+ rbug/rbug_texture.c \
+ rbug/rbug_shader.c \
+ rtasm/rtasm_cpu.c \
+ rtasm/rtasm_execmem.c \
+ rtasm/rtasm_ppc.c \
+ rtasm/rtasm_ppc_spe.c \
+ rtasm/rtasm_x86sse.c \
+ tgsi/tgsi_build.c \
+ tgsi/tgsi_dump.c \
+ tgsi/tgsi_exec.c \
+ tgsi/tgsi_info.c \
+ tgsi/tgsi_iterate.c \
+ tgsi/tgsi_parse.c \
+ tgsi/tgsi_ppc.c \
+ tgsi/tgsi_sanity.c \
+ tgsi/tgsi_scan.c \
+ tgsi/tgsi_sse2.c \
+ tgsi/tgsi_text.c \
+ tgsi/tgsi_transform.c \
+ tgsi/tgsi_ureg.c \
+ tgsi/tgsi_util.c \
+ translate/translate.c \
+ translate/translate_cache.c \
+ translate/translate_generic.c \
+ translate/translate_sse.c \
+ util/u_debug.c \
+ util/u_debug_describe.c \
+ util/u_debug_memory.c \
+ util/u_debug_refcnt.c \
+ util/u_debug_stack.c \
+ util/u_debug_symbol.c \
+ util/u_dump_defines.c \
+ util/u_dump_state.c \
+ util/u_bitmask.c \
+ util/u_blit.c \
+ util/u_blitter.c \
+ util/u_cache.c \
+ util/u_caps.c \
+ util/u_cpu_detect.c \
+ util/u_dl.c \
+ util/u_draw.c \
+ util/u_draw_quad.c \
+ util/u_format.c \
+ util/u_format_other.c \
+ util/u_format_latc.c \
+ util/u_format_s3tc.c \
+ util/u_format_rgtc.c \
+ util/u_format_tests.c \
+ util/u_format_yuv.c \
+ util/u_format_zs.c \
+ util/u_framebuffer.c \
+ util/u_gen_mipmap.c \
+ util/u_handle_table.c \
+ util/u_hash.c \
+ util/u_hash_table.c \
+ util/u_index_modify.c \
+ util/u_keymap.c \
+ util/u_linear.c \
+ util/u_linkage.c \
+ util/u_network.c \
+ util/u_math.c \
+ util/u_mm.c \
+ util/u_pstipple.c \
+ util/u_rect.c \
+ util/u_ringbuffer.c \
+ util/u_sampler.c \
+ util/u_simple_shaders.c \
+ util/u_slab.c \
+ util/u_snprintf.c \
+ util/u_staging.c \
+ util/u_surface.c \
+ util/u_surfaces.c \
+ util/u_texture.c \
+ util/u_tile.c \
+ util/u_transfer.c \
+ util/u_resource.c \
+ util/u_upload_mgr.c \
+ util/u_vbuf_mgr.c \
+ vl/vl_csc.c \
+ vl/vl_compositor.c \
+ vl/vl_decoder.c \
+ vl/vl_mpeg12_decoder.c \
+ vl/vl_mpeg12_bitstream.c \
+ vl/vl_zscan.c \
+ vl/vl_idct.c \
+ vl/vl_mc.c \
+ vl/vl_vertex_buffers.c \
+ vl/vl_video_buffer.c
+
+GENERATED_SOURCES := \
+ indices/u_indices_gen.c \
+ indices/u_unfilled_gen.c \
+ util/u_format_srgb.c \
+ util/u_format_table.c \
+ util/u_half.c
+
+GALLIVM_SOURCES := \
+ gallivm/lp_bld_arit.c \
+ gallivm/lp_bld_assert.c \
+ gallivm/lp_bld_bitarit.c \
+ gallivm/lp_bld_const.c \
+ gallivm/lp_bld_conv.c \
+ gallivm/lp_bld_flow.c \
+ gallivm/lp_bld_format_aos.c \
+ gallivm/lp_bld_format_soa.c \
+ gallivm/lp_bld_format_yuv.c \
+ gallivm/lp_bld_gather.c \
+ gallivm/lp_bld_init.c \
+ gallivm/lp_bld_intr.c \
+ gallivm/lp_bld_logic.c \
+ gallivm/lp_bld_pack.c \
+ gallivm/lp_bld_printf.c \
+ gallivm/lp_bld_quad.c \
+ gallivm/lp_bld_sample.c \
+ gallivm/lp_bld_sample_aos.c \
+ gallivm/lp_bld_sample_soa.c \
+ gallivm/lp_bld_struct.c \
+ gallivm/lp_bld_swizzle.c \
+ gallivm/lp_bld_tgsi_aos.c \
+ gallivm/lp_bld_tgsi_info.c \
+ gallivm/lp_bld_tgsi_soa.c \
+ gallivm/lp_bld_type.c \
+ draw/draw_llvm.c \
+ draw/draw_llvm_sample.c \
+ draw/draw_llvm_translate.c \
+ draw/draw_vs_llvm.c \
+ draw/draw_pt_fetch_shade_pipeline_llvm.c
+
+GALLIVM_CPP_SOURCES := \
+ gallivm/lp_bld_debug.cpp \
+ gallivm/lp_bld_misc.cpp
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index d18f55f1644..07c420e138d 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -47,201 +47,20 @@ env.Depends('util/u_format_table.c', [
'util/u_format_pack.py',
])
-source = [
- 'cso_cache/cso_cache.c',
- 'cso_cache/cso_context.c',
- 'cso_cache/cso_hash.c',
- 'draw/draw_context.c',
- 'draw/draw_fs.c',
- 'draw/draw_gs.c',
- 'draw/draw_pipe.c',
- 'draw/draw_pipe_aaline.c',
- 'draw/draw_pipe_aapoint.c',
- 'draw/draw_pipe_clip.c',
- 'draw/draw_pipe_cull.c',
- 'draw/draw_pipe_flatshade.c',
- 'draw/draw_pipe_offset.c',
- 'draw/draw_pipe_pstipple.c',
- 'draw/draw_pipe_stipple.c',
- 'draw/draw_pipe_twoside.c',
- 'draw/draw_pipe_unfilled.c',
- 'draw/draw_pipe_util.c',
- 'draw/draw_pipe_validate.c',
- 'draw/draw_pipe_vbuf.c',
- 'draw/draw_pipe_wide_line.c',
- 'draw/draw_pipe_wide_point.c',
- 'draw/draw_pt.c',
- 'draw/draw_pt_emit.c',
- 'draw/draw_pt_fetch.c',
- 'draw/draw_pt_fetch_emit.c',
- 'draw/draw_pt_fetch_shade_emit.c',
- 'draw/draw_pt_fetch_shade_pipeline.c',
- 'draw/draw_pt_post_vs.c',
- 'draw/draw_pt_so_emit.c',
- 'draw/draw_pt_util.c',
- 'draw/draw_pt_vsplit.c',
- 'draw/draw_vertex.c',
- 'draw/draw_vs.c',
- 'draw/draw_vs_aos.c',
- 'draw/draw_vs_aos_io.c',
- 'draw/draw_vs_aos_machine.c',
- 'draw/draw_vs_exec.c',
- 'draw/draw_vs_ppc.c',
- 'draw/draw_vs_sse.c',
- 'draw/draw_vs_variant.c',
- #'indices/u_indices.c',
- #'indices/u_unfilled_indices.c',
- 'indices/u_indices_gen.c',
- 'indices/u_unfilled_gen.c',
- 'os/os_misc.c',
- 'os/os_stream.c',
- 'os/os_stream_log.c',
- 'os/os_stream_null.c',
- 'os/os_stream_stdc.c',
- 'os/os_stream_str.c',
- 'os/os_time.c',
- 'pipebuffer/pb_buffer_fenced.c',
- 'pipebuffer/pb_buffer_malloc.c',
- 'pipebuffer/pb_bufmgr_alt.c',
- 'pipebuffer/pb_bufmgr_cache.c',
- 'pipebuffer/pb_bufmgr_debug.c',
- 'pipebuffer/pb_bufmgr_mm.c',
- 'pipebuffer/pb_bufmgr_ondemand.c',
- 'pipebuffer/pb_bufmgr_pool.c',
- 'pipebuffer/pb_bufmgr_slab.c',
- 'pipebuffer/pb_validate.c',
- 'rbug/rbug_connection.c',
- 'rbug/rbug_context.c',
- 'rbug/rbug_core.c',
- 'rbug/rbug_demarshal.c',
- 'rbug/rbug_shader.c',
- 'rbug/rbug_texture.c',
- 'rtasm/rtasm_cpu.c',
- 'rtasm/rtasm_execmem.c',
- 'rtasm/rtasm_ppc.c',
- 'rtasm/rtasm_ppc_spe.c',
- 'rtasm/rtasm_x86sse.c',
- 'tgsi/tgsi_build.c',
- 'tgsi/tgsi_dump.c',
- 'tgsi/tgsi_exec.c',
- 'tgsi/tgsi_info.c',
- 'tgsi/tgsi_iterate.c',
- 'tgsi/tgsi_parse.c',
- 'tgsi/tgsi_ppc.c',
- 'tgsi/tgsi_sanity.c',
- 'tgsi/tgsi_scan.c',
- 'tgsi/tgsi_sse2.c',
- 'tgsi/tgsi_text.c',
- 'tgsi/tgsi_transform.c',
- 'tgsi/tgsi_ureg.c',
- 'tgsi/tgsi_util.c',
- 'translate/translate.c',
- 'translate/translate_cache.c',
- 'translate/translate_generic.c',
- 'translate/translate_sse.c',
- 'util/u_bitmask.c',
- 'util/u_blit.c',
- 'util/u_blitter.c',
- 'util/u_cache.c',
- 'util/u_caps.c',
- 'util/u_cpu_detect.c',
- 'util/u_debug.c',
- 'util/u_debug_describe.c',
- 'util/u_debug_memory.c',
- 'util/u_debug_refcnt.c',
- 'util/u_debug_stack.c',
- 'util/u_debug_symbol.c',
- 'util/u_dump_defines.c',
- 'util/u_dump_state.c',
- 'util/u_dl.c',
- 'util/u_draw.c',
- 'util/u_draw_quad.c',
- 'util/u_format.c',
- 'util/u_format_other.c',
- 'util/u_format_latc.c',
- 'util/u_format_s3tc.c',
- 'util/u_format_rgtc.c',
- 'util/u_format_srgb.c',
- 'util/u_format_table.c',
- 'util/u_format_tests.c',
- 'util/u_format_yuv.c',
- 'util/u_format_zs.c',
- 'util/u_framebuffer.c',
- 'util/u_gen_mipmap.c',
- 'util/u_half.c',
- 'util/u_handle_table.c',
- 'util/u_hash.c',
- 'util/u_hash_table.c',
- 'util/u_index_modify.c',
- 'util/u_keymap.c',
- 'util/u_linear.c',
- 'util/u_linkage.c',
- 'util/u_network.c',
- 'util/u_math.c',
- 'util/u_mm.c',
- 'util/u_pstipple.c',
- 'util/u_rect.c',
- 'util/u_resource.c',
- 'util/u_ringbuffer.c',
- 'util/u_sampler.c',
- 'util/u_simple_shaders.c',
- 'util/u_slab.c',
- 'util/u_snprintf.c',
- 'util/u_staging.c',
- 'util/u_surface.c',
- 'util/u_surfaces.c',
- 'util/u_texture.c',
- 'util/u_tile.c',
- 'util/u_transfer.c',
- 'util/u_upload_mgr.c',
- 'util/u_vbuf_mgr.c',
- 'vl/vl_csc.c',
- 'vl/vl_compositor.c',
- 'vl/vl_decoder.c',
- 'vl/vl_mpeg12_decoder.c',
- 'vl/vl_mpeg12_bitstream.c',
- 'vl/vl_zscan.c',
- 'vl/vl_idct.c',
- 'vl/vl_mc.c',
- 'vl/vl_vertex_buffers.c',
- 'vl/vl_video_buffer.c',
-]
+source = env.ParseSourceList('Makefile.sources', [
+ 'C_SOURCES',
+ 'GENERATED_SOURCES'
+])
if env['llvm']:
- source += [
- 'gallivm/lp_bld_arit.c',
- 'gallivm/lp_bld_assert.c',
- 'gallivm/lp_bld_bitarit.c',
- 'gallivm/lp_bld_const.c',
- 'gallivm/lp_bld_conv.c',
- 'gallivm/lp_bld_debug.cpp',
- 'gallivm/lp_bld_flow.c',
- 'gallivm/lp_bld_format_aos.c',
- 'gallivm/lp_bld_format_soa.c',
- 'gallivm/lp_bld_format_yuv.c',
- 'gallivm/lp_bld_gather.c',
- 'gallivm/lp_bld_init.c',
- 'gallivm/lp_bld_intr.c',
- 'gallivm/lp_bld_logic.c',
- 'gallivm/lp_bld_misc.cpp',
- 'gallivm/lp_bld_pack.c',
- 'gallivm/lp_bld_printf.c',
- 'gallivm/lp_bld_quad.c',
- 'gallivm/lp_bld_sample.c',
- 'gallivm/lp_bld_sample_aos.c',
- 'gallivm/lp_bld_sample_soa.c',
- 'gallivm/lp_bld_struct.c',
- 'gallivm/lp_bld_swizzle.c',
- 'gallivm/lp_bld_tgsi_aos.c',
- 'gallivm/lp_bld_tgsi_info.c',
- 'gallivm/lp_bld_tgsi_soa.c',
- 'gallivm/lp_bld_type.c',
- 'draw/draw_llvm.c',
- 'draw/draw_llvm_sample.c',
- 'draw/draw_llvm_translate.c',
- 'draw/draw_pt_fetch_shade_pipeline_llvm.c',
- 'draw/draw_vs_llvm.c'
- ]
+ source += env.ParseSourceList('Makefile.sources', [
+ 'GALLIVM_SOURCES',
+ 'GALLIVM_CPP_SOURCES'
+ ])
+
+ if env['toolchain'] == 'crossmingw':
+ # compile lp_bld_misc.cpp without -gstabs option
+ source = env.compile_without_gstabs(source, "gallivm/lp_bld_misc.cpp")
gallium = env.ConvenienceLibrary(
target = 'gallium',
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 8bb87440497..996e295e4b5 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -96,7 +96,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *var);
* Create LLVM type for struct draw_jit_texture
*/
static LLVMTypeRef
-create_jit_texture_type(struct gallivm_state *gallivm)
+create_jit_texture_type(struct gallivm_state *gallivm, const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef texture_type;
@@ -120,13 +120,21 @@ create_jit_texture_type(struct gallivm_state *gallivm)
elem_types[DRAW_JIT_TEXTURE_BORDER_COLOR] =
LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
+#if HAVE_LLVM >= 0x0300
+ texture_type = LLVMStructCreateNamed(gallivm->context, struct_name);
+ LLVMStructSetBody(texture_type, elem_types,
+ Elements(elem_types), 0);
+#else
texture_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
+ LLVMAddTypeName(gallivm->module, struct_name, texture_type);
+
/* Make sure the target's struct layout cache doesn't return
* stale/invalid data.
*/
LLVMInvalidateStructLayout(gallivm->target, texture_type);
+#endif
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, width,
target, texture_type,
@@ -176,7 +184,7 @@ create_jit_texture_type(struct gallivm_state *gallivm)
*/
static LLVMTypeRef
create_jit_context_type(struct gallivm_state *gallivm,
- LLVMTypeRef texture_type)
+ LLVMTypeRef texture_type, const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
@@ -189,11 +197,17 @@ create_jit_context_type(struct gallivm_state *gallivm,
elem_types[3] = LLVMPointerType(float_type, 0); /* viewport */
elem_types[4] = LLVMArrayType(texture_type,
PIPE_MAX_VERTEX_SAMPLERS); /* textures */
-
+#if HAVE_LLVM >= 0x0300
+ context_type = LLVMStructCreateNamed(gallivm->context, struct_name);
+ LLVMStructSetBody(context_type, elem_types,
+ Elements(elem_types), 0);
+#else
context_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
+ LLVMAddTypeName(gallivm->module, struct_name, context_type);
LLVMInvalidateStructLayout(gallivm->target, context_type);
+#endif
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, vs_constants,
target, context_type, 0);
@@ -215,7 +229,7 @@ create_jit_context_type(struct gallivm_state *gallivm,
* Create LLVM type for struct pipe_vertex_buffer
*/
static LLVMTypeRef
-create_jit_vertex_buffer_type(struct gallivm_state *gallivm)
+create_jit_vertex_buffer_type(struct gallivm_state *gallivm, const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef elem_types[3];
@@ -225,10 +239,17 @@ create_jit_vertex_buffer_type(struct gallivm_state *gallivm)
elem_types[1] = LLVMInt32TypeInContext(gallivm->context);
elem_types[2] = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0); /* vs_constants */
+#if HAVE_LLVM >= 0x0300
+ vb_type = LLVMStructCreateNamed(gallivm->context, struct_name);
+ LLVMStructSetBody(vb_type, elem_types,
+ Elements(elem_types), 0);
+#else
vb_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
+ LLVMAddTypeName(gallivm->module, struct_name, vb_type);
LLVMInvalidateStructLayout(gallivm->target, vb_type);
+#endif
LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, stride,
target, vb_type, 0);
@@ -258,10 +279,17 @@ create_jit_vertex_header(struct gallivm_state *gallivm, int data_elems)
elem_types[1] = LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
elem_types[2] = LLVMArrayType(elem_types[1], data_elems);
+#if HAVE_LLVM >= 0x0300
+ vertex_header = LLVMStructCreateNamed(gallivm->context, struct_name);
+ LLVMStructSetBody(vertex_header, elem_types,
+ Elements(elem_types), 0);
+#else
vertex_header = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
+ LLVMAddTypeName(gallivm->module, struct_name, vertex_header);
LLVMInvalidateStructLayout(gallivm->target, vertex_header);
+#endif
/* these are bit-fields and we can't take address of them
LP_CHECK_MEMBER_OFFSET(struct vertex_header, clipmask,
@@ -284,8 +312,6 @@ create_jit_vertex_header(struct gallivm_state *gallivm, int data_elems)
target, vertex_header,
DRAW_JIT_VERTEX_DATA);
- LLVMAddTypeName(gallivm->module, struct_name, vertex_header);
-
return vertex_header;
}
@@ -299,19 +325,15 @@ create_jit_types(struct draw_llvm *llvm)
struct gallivm_state *gallivm = llvm->gallivm;
LLVMTypeRef texture_type, context_type, buffer_type, vb_type;
- texture_type = create_jit_texture_type(gallivm);
- LLVMAddTypeName(gallivm->module, "texture", texture_type);
+ texture_type = create_jit_texture_type(gallivm, "texture");
- context_type = create_jit_context_type(gallivm, texture_type);
- LLVMAddTypeName(gallivm->module, "draw_jit_context", context_type);
+ context_type = create_jit_context_type(gallivm, texture_type, "draw_jit_context");
llvm->context_ptr_type = LLVMPointerType(context_type, 0);
buffer_type = LLVMPointerType(LLVMIntTypeInContext(gallivm->context, 8), 0);
- LLVMAddTypeName(gallivm->module, "buffer", buffer_type);
llvm->buffer_ptr_type = LLVMPointerType(buffer_type, 0);
- vb_type = create_jit_vertex_buffer_type(gallivm);
- LLVMAddTypeName(gallivm->module, "pipe_vertex_buffer", vb_type);
+ vb_type = create_jit_vertex_buffer_type(gallivm, "pipe_vertex_buffer");
llvm->vb_ptr_type = LLVMPointerType(vb_type, 0);
}
diff --git a/src/gallium/auxiliary/gallivm/f.cpp b/src/gallium/auxiliary/gallivm/f.cpp
index 5eb09c01ab3..6b9c35b3ce5 100644
--- a/src/gallium/auxiliary/gallivm/f.cpp
+++ b/src/gallium/auxiliary/gallivm/f.cpp
@@ -15,8 +15,9 @@
*
* How to use this source:
*
- * - Download and abuild the NTL library from
- * http://shoup.net/ntl/download.html
+ * - Download and build the NTL library from
+ * http://shoup.net/ntl/download.html , or install libntl-dev package if on
+ * Debian.
*
* - Download boost source code matching to your distro.
*
@@ -24,22 +25,32 @@
*
* - Build as
*
- * g++ -o minimax -I /path/to/ntl/include main.cpp f.cpp /path/to/ntl/src/ntl.a -lboost_math_tr1
+ * g++ -o minimax -I /path/to/ntl/include main.cpp f.cpp /path/to/ntl/src/ntl.a
*
* - Run as
*
* ./minimax
*
- * - For example, to compute exp2 5th order polynomial between [0, 1] do:
+ * - For example, to compute log2 5th order polynomial between [1, 2] do:
+ *
+ * variant 0
+ * range 1 2
+ * order 5 0
+ * step 200
+ * info
+ *
+ * and take the coefficients from the P = { ... } array.
+ *
+ * - To compute exp2 5th order polynomial between [0, 1] do:
*
* variant 1
* range 0 1
* order 5 0
- * steps 200
+ * step 200
* info
*
* - For more info see
- * http://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals2/minimax.html
+ * http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals2/minimax.html
*/
#define L22
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index 02b3bde7893..2be8598704e 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -61,7 +61,7 @@
#include "lp_bld_arit.h"
-#define EXP_POLY_DEGREE 3
+#define EXP_POLY_DEGREE 5
#define LOG_POLY_DEGREE 5
@@ -1645,7 +1645,7 @@ lp_build_rsqrt(struct lp_build_context *bld,
assert(type.floating);
if (util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
- const unsigned num_iterations = 0;
+ const unsigned num_iterations = 1;
LLVMValueRef res;
unsigned i;
@@ -2151,7 +2151,7 @@ lp_build_exp(struct lp_build_context *bld,
assert(lp_check_value(bld->type, x));
- return lp_build_mul(bld, log2e, lp_build_exp2(bld, x));
+ return lp_build_exp2(bld, lp_build_mul(bld, log2e, x));
}
@@ -2168,7 +2168,7 @@ lp_build_log(struct lp_build_context *bld,
assert(lp_check_value(bld->type, x));
- return lp_build_mul(bld, log2, lp_build_exp2(bld, x));
+ return lp_build_mul(bld, log2, lp_build_log2(bld, x));
}
@@ -2218,18 +2218,18 @@ lp_build_polynomial(struct lp_build_context *bld,
*/
const double lp_build_exp2_polynomial[] = {
#if EXP_POLY_DEGREE == 5
- 0.999999999690134838155,
- 0.583974334321735217258,
- 0.164553105719676828492,
- 0.0292811063701710962255,
- 0.00354944426657875141846,
- 0.000296253726543423377365
+ 0.999999925063526176901,
+ 0.693153073200168932794,
+ 0.240153617044375388211,
+ 0.0558263180532956664775,
+ 0.00898934009049466391101,
+ 0.00187757667519147912699
#elif EXP_POLY_DEGREE == 4
- 1.00000001502262084505,
- 0.563586057338685991394,
- 0.150436017652442413623,
- 0.0243220604213317927308,
- 0.0025359088446580436489
+ 1.00000259337069434683,
+ 0.693003834469974940458,
+ 0.24144275689150793076,
+ 0.0520114606103070150235,
+ 0.0135341679161270268764
#elif EXP_POLY_DEGREE == 3
0.999925218562710312959,
0.695833540494823811697,
@@ -2465,6 +2465,12 @@ lp_build_log2_approx(struct lp_build_context *bld,
assert(type.floating && type.width == 32);
+ /*
+ * We don't explicitly handle denormalized numbers. They will yield a
+ * result in the neighbourhood of -127, which appears to be adequate
+ * enough.
+ */
+
i = LLVMBuildBitCast(builder, x, int_vec_type, "");
/* exp = (float) exponent(x) */
diff --git a/src/gallium/auxiliary/os/os_mman.h b/src/gallium/auxiliary/os/os_mman.h
new file mode 100644
index 00000000000..b48eb053023
--- /dev/null
+++ b/src/gallium/auxiliary/os/os_mman.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * Copyright 2011 LunarG, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * OS independent memory mapping (with large file support).
+ *
+ * @author Chia-I Wu <[email protected]>
+ */
+
+#ifndef _OS_MMAN_H_
+#define _OS_MMAN_H_
+
+
+#include "pipe/p_config.h"
+#include "pipe/p_compiler.h"
+
+#if defined(PIPE_OS_UNIX)
+# ifndef _FILE_OFFSET_BITS
+# error _FILE_OFFSET_BITS must be defined to 64
+# endif
+# include <sys/mman.h>
+#else
+# error Unsupported OS
+#endif
+
+#if defined(PIPE_OS_ANDROID)
+# include <errno.h> /* for EINVAL */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(PIPE_OS_ANDROID)
+
+extern void *__mmap2(void *, size_t, int, int, int, size_t);
+
+static INLINE void *os_mmap(void *addr, size_t length, int prot, int flags, int fd, loff_t offset)
+{
+ /* offset must be aligned to 4096 (not necessarily the page size) */
+ if (unlikely(offset & 4095)) {
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ return __mmap2(addr, length, prot, flags, fd, (size_t) (offset >> 12));
+}
+
+#else
+/* assume large file support exists */
+# define os_mmap(addr, length, prot, flags, fd, offset) mmap(addr, length, prot, flags, fd, offset)
+#endif
+
+#define os_munmap(addr, length) munmap(addr, length)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_MMAN_H_ */
diff --git a/src/gallium/auxiliary/os/os_thread.h b/src/gallium/auxiliary/os/os_thread.h
index 8f1245bff55..d8301298b7f 100644
--- a/src/gallium/auxiliary/os/os_thread.h
+++ b/src/gallium/auxiliary/os/os_thread.h
@@ -314,7 +314,7 @@ typedef int64_t pipe_condvar;
* pipe_barrier
*/
-#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)
+#if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU)) && !defined(PIPE_OS_ANDROID)
typedef pthread_barrier_t pipe_barrier;
diff --git a/src/gallium/auxiliary/postprocess/ADDING b/src/gallium/auxiliary/postprocess/ADDING
new file mode 100644
index 00000000000..3735835142a
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/ADDING
@@ -0,0 +1,87 @@
+How to add a new post-processing filter
+=======================================
+
+The Gallium post-processing queue works by passing the current screen to a fragment shader.
+These shaders may be written in any supported language, but are added here in TGSI text
+assembly.
+
+You can translate GLSL/ARB fairly easily via llvmpipe (LP_DEBUG=tgsi). I don't know the
+status of the D3D state tracker, but if/when that works, I'd assume HLSL would be possible
+too.
+
+
+
+Steps
+=====
+
+1. Add it to PP
+2. Make it known to PP
+3. Make it known to driconf
+4. ????
+5. Profit
+
+
+
+
+1. Add it to PP
+---------------
+
+Once you have the shader(s) in TGSI asm, put them to static const char arrays in a header
+file (see pp_colors.h).
+
+Add the filter's prototypes (main and init functions) to postprocess.h. This is mostly a
+copy-paste job with only changing the name.
+
+Then create a file containing empty main and init functions, named as you specified above.
+See pp_colors.c for an example.
+
+
+
+2. Make it known to PP
+----------------------
+
+Add your filter to filters.h, in a correct place. Placement is important, AA should usually
+be the last effect in the queue for example.
+
+Name is the config option your filter will be enabled by, both in driconf and as an env var.
+
+Inner temp means an intermediate framebuffer you may use in your filter to store
+results between passes. If you have a single-pass filter, request 0 of those.
+
+Shaders is the number of shaders your filter needs. The minimum is 2.
+
+
+You could also write the init and main functions now. If your filter is single-pass without
+a vertex shader and any other input than the main screen, you can use pp_nocolor as your
+main function as is.
+
+
+
+3. Make it known to driconf
+---------------------------
+
+First time outside of auxiliary/postprocess. First, add a suitable description to
+drivers/dri/common/xmlpool/t_options.h, and regenerate options.h by running make in that
+directory. Use the name you put into filters.h as the config option name.
+
+With driconf aware of the option, make Gallium aware of it too. Add it to
+state_trackers/dri/common/dri_screen.c in a proper section, specifying its default value and
+the accepted range (if applicable).
+
+Do check that __driNConfigOptions is still correct after the addition.
+
+
+
+4. ????
+-------
+
+Testing, praying, hookers, blow, sacrificial lambs...
+
+
+
+5. Profit
+---------
+
+Assuming you got here, sharing is caring. Send your filter to mesa-dev.
+
+
diff --git a/src/gallium/auxiliary/postprocess/filters.h b/src/gallium/auxiliary/postprocess/filters.h
new file mode 100644
index 00000000000..2454088707d
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/filters.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PP_EXTERNAL_FILTERS_H
+#define PP_EXTERNAL_FILTERS_H
+
+#include "postprocess/postprocess.h"
+
+typedef void (*pp_init_func) (struct pp_queue_t *, unsigned int,
+ unsigned int);
+
+struct pp_filter_t
+{
+ const char *name; /* Config name */
+ unsigned int inner_tmps; /* Request how many inner temps */
+ unsigned int shaders; /* Request how many shaders */
+ unsigned int verts; /* How many are vertex shaders */
+ pp_init_func init; /* Init function */
+ pp_func main; /* Run function */
+};
+
+/* Order matters. Put new filters in a suitable place. */
+
+static const struct pp_filter_t pp_filters[PP_FILTERS] = {
+/* name inner shaders verts init run */
+ { "pp_noblue", 0, 2, 1, pp_noblue_init, pp_nocolor },
+ { "pp_nogreen", 0, 2, 1, pp_nogreen_init, pp_nocolor },
+ { "pp_nored", 0, 2, 1, pp_nored_init, pp_nocolor },
+ { "pp_celshade", 0, 2, 1, pp_celshade_init, pp_nocolor },
+ { "pp_jimenezmlaa", 2, 5, 2, pp_jimenezmlaa_init, pp_jimenezmlaa },
+ { "pp_jimenezmlaa_color", 2, 5, 2, pp_jimenezmlaa_init_color, pp_jimenezmlaa_color },
+};
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/postprocess.h b/src/gallium/auxiliary/postprocess/postprocess.h
new file mode 100644
index 00000000000..ef94f79997a
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/postprocess.h
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef POSTPROCESS_H
+#define POSTPROCESS_H
+
+#include "postprocess/pp_program.h"
+
+#define PP_FILTERS 6 /* Increment this if you add filters */
+#define PP_MAX_PASSES 6
+
+struct pp_queue_t; /* Forward definition */
+
+/* Less typing later on */
+typedef void (*pp_func) (struct pp_queue_t *, struct pipe_resource *,
+ struct pipe_resource *, unsigned int);
+/**
+* The main post-processing queue.
+*/
+struct pp_queue_t
+{
+ pp_func *pp_queue; /* An array of pp_funcs */
+ unsigned int n_filters; /* Number of enabled filters */
+
+ struct pipe_resource *tmp[2]; /* Two temp FBOs for the queue */
+ struct pipe_resource *inner_tmp[3]; /* Three for filter use */
+
+ unsigned int n_tmp, n_inner_tmp;
+
+ struct pipe_resource *depth; /* depth of original input */
+ struct pipe_resource *stencil; /* stencil shared by inner_tmps */
+
+ struct pipe_surface *tmps[2], *inner_tmps[3], *stencils;
+
+ void ***shaders; /* Shaders in TGSI form */
+ unsigned int *verts;
+ struct program *p;
+
+ bool fbos_init;
+};
+
+/* Main functions */
+
+struct pp_queue_t *pp_init(struct pipe_screen *, const unsigned int *);
+void pp_run(struct pp_queue_t *, struct pipe_resource *,
+ struct pipe_resource *, struct pipe_resource *);
+void pp_free(struct pp_queue_t *);
+void pp_free_fbos(struct pp_queue_t *);
+void pp_debug(const char *, ...);
+struct program *pp_init_prog(struct pp_queue_t *, struct pipe_screen *);
+void pp_init_fbos(struct pp_queue_t *, unsigned int, unsigned int,
+ struct pipe_resource *);
+
+/* The filters */
+
+void pp_nocolor(struct pp_queue_t *, struct pipe_resource *,
+ struct pipe_resource *, unsigned int);
+
+void pp_jimenezmlaa(struct pp_queue_t *, struct pipe_resource *,
+ struct pipe_resource *, unsigned int);
+void pp_jimenezmlaa_color(struct pp_queue_t *, struct pipe_resource *,
+ struct pipe_resource *, unsigned int);
+
+/* The filter init functions */
+
+void pp_celshade_init(struct pp_queue_t *, unsigned int, unsigned int);
+
+void pp_nored_init(struct pp_queue_t *, unsigned int, unsigned int);
+void pp_nogreen_init(struct pp_queue_t *, unsigned int, unsigned int);
+void pp_noblue_init(struct pp_queue_t *, unsigned int, unsigned int);
+
+void pp_jimenezmlaa_init(struct pp_queue_t *, unsigned int, unsigned int);
+void pp_jimenezmlaa_init_color(struct pp_queue_t *, unsigned int,
+ unsigned int);
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/pp_celshade.c b/src/gallium/auxiliary/postprocess/pp_celshade.c
new file mode 100644
index 00000000000..4454764ea84
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_celshade.c
@@ -0,0 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "postprocess/postprocess.h"
+#include "postprocess/pp_celshade.h"
+#include "postprocess/pp_filters.h"
+
+/** Init function */
+void
+pp_celshade_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
+{
+ ppq->shaders[n][1] =
+ pp_tgsi_to_state(ppq->p->pipe, celshade, false, "celshade");
+}
diff --git a/src/gallium/auxiliary/postprocess/pp_celshade.h b/src/gallium/auxiliary/postprocess/pp_celshade.h
new file mode 100644
index 00000000000..536ac7f1f1c
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_celshade.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef CELSHADE_H
+#define CELSHADE_H
+
+static const char celshade[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL TEMP[0..4]\n"
+ "IMM FLT32 { 0.2126, 0.7152, 0.0722, 4.0000}\n"
+ "IMM FLT32 { 0.5000, 2.0000, 1.0000, -0.1250}\n"
+ "IMM FLT32 { 0.2500, 0.1000, 0.1250, 3.0000}\n"
+ " 0: TEX TEMP[0], IN[0].xyyy, SAMP[0], 2D\n"
+ " 1: DP3 TEMP[1].x, TEMP[0].xyzz, IMM[0]\n"
+ " 2: MUL TEMP[3].x, TEMP[1].xxxx, IMM[0].wwww\n"
+ " 3: ROUND TEMP[2].x, TEMP[3].xxxx\n"
+ " 4: MUL TEMP[3].x, TEMP[2].xxxx, IMM[2].xxxx\n"
+ " 5: MOV TEMP[2].x, TEMP[3].xxxx\n"
+ " 6: ADD TEMP[4].x, TEMP[1].xxxx, -TEMP[3].xxxx\n"
+ " 7: SGT TEMP[1].w, TEMP[4].xxxx, IMM[2].yyyy\n"
+ " 8: IF TEMP[1].wwww :19\n"
+ " 9: ADD TEMP[4].y, TEMP[3].xxxx, IMM[2].yyyy\n"
+ " 10: ADD TEMP[1].z, TEMP[1].xxxx, -TEMP[4].yyyy\n"
+ " 11: ADD TEMP[1].y, TEMP[3].xxxx, IMM[2].zzzz\n"
+ " 12: ADD TEMP[2].x, TEMP[1].yyyy, -TEMP[4].yyyy\n"
+ " 13: RCP TEMP[4].y, TEMP[2].xxxx\n"
+ " 14: MUL TEMP[2].x, TEMP[1].zzzz, TEMP[4].yyyy\n"
+ " 15: MAD TEMP[1].y, -IMM[1].yyyy, TEMP[2].xxxx, IMM[2].wwww\n"
+ " 16: MUL TEMP[1].z, TEMP[2].xxxx, TEMP[1].yyyy\n"
+ " 17: MUL TEMP[1].y, TEMP[2].xxxx, TEMP[1].zzzz\n"
+ " 18: MAD TEMP[2].x, TEMP[1].yyyy, IMM[2].zzzz, TEMP[3].xxxx\n"
+ " 19: ENDIF\n"
+ " 20: SLT TEMP[3].x, TEMP[4].xxxx, -IMM[2].yyyy\n"
+ " 21: IF TEMP[3].xxxx :34\n"
+ " 22: ADD TEMP[3].x, TEMP[2].xxxx, -IMM[2].zzzz\n"
+ " 23: ADD TEMP[4].x, TEMP[1].xxxx, -TEMP[3].xxxx\n"
+ " 24: ADD TEMP[1].x, TEMP[2].xxxx, -IMM[2].yyyy\n"
+ " 25: ADD TEMP[4].y, TEMP[1].xxxx, -TEMP[3].xxxx\n"
+ " 26: RCP TEMP[3].x, TEMP[4].yyyy\n"
+ " 27: MUL TEMP[1].x, TEMP[4].xxxx, TEMP[3].xxxx\n"
+ " 28: MAD TEMP[4].x, -IMM[1].yyyy, TEMP[1].xxxx, IMM[2].wwww\n"
+ " 29: MUL TEMP[3].x, TEMP[1].xxxx, TEMP[4].xxxx\n"
+ " 30: MUL TEMP[4].x, TEMP[1].xxxx, TEMP[3].xxxx\n"
+ " 31: ADD TEMP[3].x, IMM[1].zzzz, -TEMP[4].xxxx\n"
+ " 32: MAD TEMP[1].x, TEMP[3].xxxx, -IMM[2].zzzz, TEMP[2].xxxx\n"
+ " 33: MOV TEMP[2].x, TEMP[1].xxxx\n"
+ " 34: ENDIF\n"
+ " 35: MAD TEMP[1].x, TEMP[2].xxxx, IMM[1].yyyy, IMM[2].yyyy\n"
+ " 36: MUL OUT[0], TEMP[0], TEMP[1].xxxx\n"
+ " 37: END\n";
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/pp_colors.c b/src/gallium/auxiliary/postprocess/pp_colors.c
new file mode 100644
index 00000000000..36bb1f552f5
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_colors.c
@@ -0,0 +1,80 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "postprocess/postprocess.h"
+#include "postprocess/pp_colors.h"
+#include "postprocess/pp_filters.h"
+
+/** The run function of the color filters */
+void
+pp_nocolor(struct pp_queue_t *ppq, struct pipe_resource *in,
+ struct pipe_resource *out, unsigned int n)
+{
+
+ struct program *p = ppq->p;
+
+ pp_filter_setup_in(p, in);
+ pp_filter_setup_out(p, out);
+
+ pp_filter_set_fb(p);
+ pp_filter_misc_state(p);
+
+ cso_single_sampler(p->cso, 0, &p->sampler_point);
+ cso_single_sampler_done(p->cso);
+ cso_set_fragment_sampler_views(p->cso, 1, &p->view);
+
+ cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][0]);
+ cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][1]);
+
+ pp_filter_draw(p);
+ pp_filter_end_pass(p);
+}
+
+
+/* Init functions */
+
+void
+pp_nored_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
+{
+ ppq->shaders[n][1] = pp_tgsi_to_state(ppq->p->pipe, nored, false, "nored");
+}
+
+
+void
+pp_nogreen_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
+{
+ ppq->shaders[n][1] =
+ pp_tgsi_to_state(ppq->p->pipe, nogreen, false, "nogreen");
+}
+
+
+void
+pp_noblue_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
+{
+ ppq->shaders[n][1] =
+ pp_tgsi_to_state(ppq->p->pipe, noblue, false, "noblue");
+}
diff --git a/src/gallium/auxiliary/postprocess/pp_colors.h b/src/gallium/auxiliary/postprocess/pp_colors.h
new file mode 100644
index 00000000000..588cd2f0c52
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_colors.h
@@ -0,0 +1,69 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PP_COLORS_H
+#define PP_COLORS_H
+
+static const char nored[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL TEMP[0]\n"
+ "IMM FLT32 { 0.0000, 0.0000, 0.0000, 0.0000}\n"
+ " 0: TEX TEMP[0], IN[0].xyyy, SAMP[0], 2D\n"
+ " 1: MOV TEMP[0].x, IMM[0].xxxx\n"
+ " 2: MOV OUT[0], TEMP[0]\n"
+ " 3: END\n";
+
+
+static const char nogreen[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL TEMP[0]\n"
+ "IMM FLT32 { 0.0000, 0.0000, 0.0000, 0.0000}\n"
+ " 0: TEX TEMP[0], IN[0].xyyy, SAMP[0], 2D\n"
+ " 1: MOV TEMP[0].y, IMM[0].xxxx\n"
+ " 2: MOV OUT[0], TEMP[0]\n"
+ " 3: END\n";
+
+
+static const char noblue[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL TEMP[0]\n"
+ "IMM FLT32 { 0.0000, 0.0000, 0.0000, 0.0000}\n"
+ " 0: TEX TEMP[0], IN[0].xyyy, SAMP[0], 2D\n"
+ " 1: MOV TEMP[0].z, IMM[0].xxxx\n"
+ " 2: MOV OUT[0], TEMP[0]\n"
+ " 3: END\n";
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/pp_filters.h b/src/gallium/auxiliary/postprocess/pp_filters.h
new file mode 100644
index 00000000000..0e34bb6d20f
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_filters.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PP_FILTERS_H
+#define PP_FILTERS_H
+
+/* Internal include, mainly for the filters */
+
+#include "cso_cache/cso_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_shader_tokens.h"
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_text.h"
+#include "util/u_memory.h"
+#include "util/u_draw_quad.h"
+
+#define PP_MAX_TOKENS 2048
+
+
+/* Helper functions for the filters */
+
+void pp_filter_setup_in(struct program *, struct pipe_resource *);
+void pp_filter_setup_out(struct program *, struct pipe_resource *);
+void pp_filter_end_pass(struct program *);
+void *pp_tgsi_to_state(struct pipe_context *, const char *, bool,
+ const char *);
+void pp_filter_misc_state(struct program *);
+void pp_filter_draw(struct program *);
+void pp_filter_set_fb(struct program *);
+void pp_filter_set_clear_fb(struct program *);
+
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/pp_init.c b/src/gallium/auxiliary/postprocess/pp_init.c
new file mode 100644
index 00000000000..75417999b7e
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_init.c
@@ -0,0 +1,283 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "postprocess/filters.h"
+
+#include "pipe/p_screen.h"
+#include "util/u_inlines.h"
+#include "util/u_blit.h"
+#include "util/u_math.h"
+#include "cso_cache/cso_context.h"
+
+/** Initialize the post-processing queue. */
+struct pp_queue_t *
+pp_init(struct pipe_screen *pscreen, const unsigned int *enabled)
+{
+
+ unsigned int curpos = 0, i, tmp_req = 0;
+ struct pp_queue_t *ppq;
+ pp_func *tmp_q;
+
+ pp_debug("Initializing the post-processing queue.\n");
+
+ /* How many filters were requested? */
+ for (i = 0; i < PP_FILTERS; i++) {
+ if (enabled[i])
+ curpos++;
+ }
+ if (!curpos)
+ return NULL;
+
+ ppq = calloc(1, sizeof(struct pp_queue_t));
+ tmp_q = calloc(curpos, sizeof(pp_func));
+ ppq->shaders = calloc(curpos, sizeof(void *));
+ ppq->verts = calloc(curpos, sizeof(unsigned int));
+
+ if (!tmp_q || !ppq || !ppq->shaders || !ppq->verts)
+ goto error;
+
+ ppq->p = pp_init_prog(ppq, pscreen);
+ if (!ppq->p)
+ goto error;
+
+ /* Add the enabled filters to the queue, in order */
+ curpos = 0;
+ ppq->pp_queue = tmp_q;
+ for (i = 0; i < PP_FILTERS; i++) {
+ if (enabled[i]) {
+ ppq->pp_queue[curpos] = pp_filters[i].main;
+ tmp_req = MAX2(tmp_req, pp_filters[i].inner_tmps);
+
+ if (pp_filters[i].shaders) {
+ ppq->shaders[curpos] =
+ calloc(pp_filters[i].shaders + 1, sizeof(void *));
+ ppq->verts[curpos] = pp_filters[i].verts;
+ if (!ppq->shaders[curpos])
+ goto error;
+ }
+ pp_filters[i].init(ppq, curpos, enabled[i]);
+
+ curpos++;
+ }
+ }
+
+ ppq->p->blitctx = util_create_blit(ppq->p->pipe, ppq->p->cso);
+ if (!ppq->p->blitctx)
+ goto error;
+
+ ppq->n_filters = curpos;
+ ppq->n_tmp = (curpos > 2 ? 2 : 1);
+ ppq->n_inner_tmp = tmp_req;
+
+ ppq->fbos_init = false;
+
+ for (i = 0; i < curpos; i++)
+ ppq->shaders[i][0] = ppq->p->passvs;
+
+ pp_debug("Queue successfully allocated. %u filter(s).\n", curpos);
+
+ return ppq;
+
+ error:
+ pp_debug("Error setting up pp\n");
+
+ if (ppq)
+ free(ppq->p);
+ free(ppq);
+ free(tmp_q);
+
+ return NULL;
+}
+
+/** Free any allocated FBOs (temp buffers). Called after resizing for example. */
+void
+pp_free_fbos(struct pp_queue_t *ppq)
+{
+
+ unsigned int i;
+
+ if (!ppq->fbos_init)
+ return;
+
+ for (i = 0; i < ppq->n_tmp; i++) {
+ pipe_surface_reference(&ppq->tmps[i], NULL);
+ pipe_resource_reference(&ppq->tmp[i], NULL);
+ }
+ for (i = 0; i < ppq->n_inner_tmp; i++) {
+ pipe_surface_reference(&ppq->inner_tmps[i], NULL);
+ pipe_resource_reference(&ppq->inner_tmp[i], NULL);
+ }
+ pipe_surface_reference(&ppq->stencils, NULL);
+ pipe_resource_reference(&ppq->stencil, NULL);
+
+ ppq->fbos_init = false;
+}
+
+/** Free the pp queue. Called on context termination. */
+void
+pp_free(struct pp_queue_t *ppq)
+{
+
+ unsigned int i, j;
+
+ pp_free_fbos(ppq);
+
+ util_destroy_blit(ppq->p->blitctx);
+
+ cso_set_fragment_sampler_views(ppq->p->cso, 0, NULL);
+ cso_release_all(ppq->p->cso);
+
+ for (i = 0; i < ppq->n_filters; i++) {
+ for (j = 0; j < PP_MAX_PASSES && ppq->shaders[i][j]; j++) {
+ if (j >= ppq->verts[i]) {
+ ppq->p->pipe->delete_fs_state(ppq->p->pipe, ppq->shaders[i][j]);
+ ppq->shaders[i][j] = NULL;
+ }
+ else if (ppq->shaders[i][j] != ppq->p->passvs) {
+ ppq->p->pipe->delete_vs_state(ppq->p->pipe, ppq->shaders[i][j]);
+ ppq->shaders[i][j] = NULL;
+ }
+ }
+ }
+
+ cso_destroy_context(ppq->p->cso);
+ ppq->p->pipe->destroy(ppq->p->pipe);
+
+ free(ppq->p);
+ free(ppq->pp_queue);
+ free(ppq);
+
+ pp_debug("Queue taken down.\n");
+}
+
+/** Internal debug function. Should be available to final users. */
+void
+pp_debug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (!getenv("PP_DEBUG"))
+ return;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+/** Allocate the temp FBOs. Called on makecurrent and resize. */
+void
+pp_init_fbos(struct pp_queue_t *ppq, const unsigned int w,
+ const unsigned int h, struct pipe_resource *indepth)
+{
+
+ struct program *p = ppq->p; /* The lazy will inherit the earth */
+
+ unsigned int i;
+ struct pipe_resource tmp_res;
+
+ if (ppq->fbos_init)
+ return;
+
+ pp_debug("Initializing FBOs, size %ux%u\n", w, h);
+ pp_debug("Requesting %u temps and %u inner temps\n", ppq->n_tmp,
+ ppq->n_inner_tmp);
+
+ memset(&tmp_res, 0, sizeof(tmp_res));
+ tmp_res.target = PIPE_TEXTURE_2D;
+ tmp_res.format = p->surf.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ tmp_res.width0 = w;
+ tmp_res.height0 = h;
+ tmp_res.depth0 = 1;
+ tmp_res.array_size = 1;
+ tmp_res.last_level = 0;
+ tmp_res.bind = p->surf.usage = PIPE_BIND_RENDER_TARGET;
+
+ if (!p->screen->is_format_supported(p->screen, tmp_res.format,
+ tmp_res.target, 1, tmp_res.bind))
+ pp_debug("Temp buffers' format fail\n");
+
+ for (i = 0; i < ppq->n_tmp; i++) {
+ ppq->tmp[i] = p->screen->resource_create(p->screen, &tmp_res);
+ ppq->tmps[i] = p->pipe->create_surface(p->pipe, ppq->tmp[i], &p->surf);
+
+ if (!ppq->tmp[i] || !ppq->tmps[i])
+ goto error;
+ }
+
+ for (i = 0; i < ppq->n_inner_tmp; i++) {
+ ppq->inner_tmp[i] = p->screen->resource_create(p->screen, &tmp_res);
+ ppq->inner_tmps[i] = p->pipe->create_surface(p->pipe,
+ ppq->inner_tmp[i],
+ &p->surf);
+
+ if (!ppq->inner_tmp[i] || !ppq->inner_tmps[i])
+ goto error;
+ }
+
+ tmp_res.format = p->surf.format = indepth->format;
+ tmp_res.bind = p->surf.usage = PIPE_BIND_DEPTH_STENCIL;
+ ppq->depth = indepth;
+ if (!ppq->depth)
+ goto error;
+
+ tmp_res.format = p->surf.format = PIPE_FORMAT_S8_USCALED_Z24_UNORM;
+
+ if (!p->screen->is_format_supported(p->screen, tmp_res.format,
+ tmp_res.target, 1, tmp_res.bind)) {
+
+ tmp_res.format = p->surf.format = PIPE_FORMAT_Z24_UNORM_S8_USCALED;
+
+ if (!p->screen->is_format_supported(p->screen, tmp_res.format,
+ tmp_res.target, 1, tmp_res.bind))
+ pp_debug("Temp Sbuffer format fail\n");
+ }
+
+ ppq->stencil = p->screen->resource_create(p->screen, &tmp_res);
+ ppq->stencils = p->pipe->create_surface(p->pipe, ppq->stencil, &p->surf);
+ if (!ppq->stencil || !ppq->stencils)
+ goto error;
+
+
+ p->framebuffer.width = w;
+ p->framebuffer.height = h;
+
+ p->viewport.scale[0] = p->viewport.translate[0] = (float) w / 2.0;
+ p->viewport.scale[1] = p->viewport.translate[1] = (float) h / 2.0;
+ p->viewport.scale[3] = 1.0f;
+ p->viewport.translate[3] = 0.0f;
+
+ ppq->fbos_init = true;
+
+ return;
+
+ error:
+ pp_debug("Failed to allocate temp buffers!\n");
+}
diff --git a/src/gallium/auxiliary/postprocess/pp_mlaa.c b/src/gallium/auxiliary/postprocess/pp_mlaa.c
new file mode 100644
index 00000000000..476502fca93
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_mlaa.c
@@ -0,0 +1,304 @@
+/**
+ * Copyright (C) 2010 Jorge Jimenez ([email protected])
+ * Copyright (C) 2010 Belen Masia ([email protected])
+ * Copyright (C) 2010 Jose I. Echevarria ([email protected])
+ * Copyright (C) 2010 Fernando Navarro ([email protected])
+ * Copyright (C) 2010 Diego Gutierrez ([email protected])
+ * Copyright (C) 2011 Lauri Kasanen ([email protected])
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the following statement:
+ *
+ * "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia,
+ * Jose I. Echevarria, Fernando Navarro and Diego Gutierrez."
+ *
+ * Only for use in the Mesa project, this point 2 is filled by naming the
+ * technique Jimenez's MLAA in the Mesa config options.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the copyright holders.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "postprocess/postprocess.h"
+#include "postprocess/pp_mlaa.h"
+#include "postprocess/pp_filters.h"
+#include "util/u_blit.h"
+#include "util/u_box.h"
+#include "util/u_sampler.h"
+#include "util/u_inlines.h"
+#include "pipe/p_screen.h"
+
+#define IMM_SPACE 80
+
+static float constants[] = { 1, 1, 0, 0 };
+static unsigned int dimensions[2] = { 0, 0 };
+
+static struct pipe_resource *constbuf, *areamaptex;
+
+/** Upload the constants. */
+static void
+up_consts(struct pipe_context *pipe)
+{
+ struct pipe_box box;
+
+ u_box_2d(0, 0, sizeof(constants), 1, &box);
+ pipe->transfer_inline_write(pipe, constbuf, 0, PIPE_TRANSFER_WRITE,
+ &box, constants, sizeof(constants),
+ sizeof(constants));
+}
+
+/** Run function of the MLAA filter. */
+static void
+pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
+ struct pipe_resource *out, unsigned int n, bool iscolor)
+{
+
+ struct program *p = ppq->p;
+
+ struct pipe_depth_stencil_alpha_state mstencil;
+ struct pipe_sampler_view v_tmp, *arr[3];
+
+ unsigned int w = p->framebuffer.width;
+ unsigned int h = p->framebuffer.height;
+
+ const struct pipe_stencil_ref ref = { {1} };
+ memset(&mstencil, 0, sizeof(mstencil));
+ cso_set_stencil_ref(p->cso, &ref);
+
+ /* Init the pixel size constant */
+ if (dimensions[0] != p->framebuffer.width ||
+ dimensions[1] != p->framebuffer.height) {
+ constants[0] = 1.0 / p->framebuffer.width;
+ constants[1] = 1.0 / p->framebuffer.height;
+
+ up_consts(p->pipe);
+ dimensions[0] = p->framebuffer.width;
+ dimensions[1] = p->framebuffer.height;
+ }
+
+ p->pipe->set_constant_buffer(p->pipe, PIPE_SHADER_VERTEX, 0, constbuf);
+ p->pipe->set_constant_buffer(p->pipe, PIPE_SHADER_FRAGMENT, 0, constbuf);
+
+ mstencil.stencil[0].enabled = 1;
+ mstencil.stencil[0].valuemask = mstencil.stencil[0].writemask = ~0;
+ mstencil.stencil[0].func = PIPE_FUNC_ALWAYS;
+ mstencil.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ mstencil.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+
+ p->framebuffer.zsbuf = ppq->stencils;
+
+ /* First pass: depth edge detection */
+ if (iscolor)
+ pp_filter_setup_in(p, in);
+ else
+ pp_filter_setup_in(p, ppq->depth);
+
+ pp_filter_setup_out(p, ppq->inner_tmp[0]);
+
+ pp_filter_set_fb(p);
+ pp_filter_misc_state(p);
+ cso_set_depth_stencil_alpha(p->cso, &mstencil);
+ p->pipe->clear(p->pipe, PIPE_CLEAR_STENCIL | PIPE_CLEAR_COLOR,
+ p->clear_color, 0, 0);
+
+ cso_single_sampler(p->cso, 0, &p->sampler_point);
+ cso_single_sampler_done(p->cso);
+ cso_set_fragment_sampler_views(p->cso, 1, &p->view);
+
+ cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]); /* offsetvs */
+ cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][2]);
+
+ pp_filter_draw(p);
+ pp_filter_end_pass(p);
+
+
+ /* Second pass: blend weights */
+ /* Sampler order: areamap, edgesmap, edgesmapL (reversed, thx compiler) */
+ mstencil.stencil[0].func = PIPE_FUNC_EQUAL;
+ mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_KEEP;
+ cso_set_depth_stencil_alpha(p->cso, &mstencil);
+
+ pp_filter_setup_in(p, areamaptex);
+ pp_filter_setup_out(p, ppq->inner_tmp[1]);
+
+ u_sampler_view_default_template(&v_tmp, ppq->inner_tmp[0],
+ ppq->inner_tmp[0]->format);
+ arr[1] = arr[2] = p->pipe->create_sampler_view(p->pipe,
+ ppq->inner_tmp[0], &v_tmp);
+
+ pp_filter_set_clear_fb(p);
+
+ cso_single_sampler(p->cso, 0, &p->sampler_point);
+ cso_single_sampler(p->cso, 1, &p->sampler_point);
+ cso_single_sampler(p->cso, 2, &p->sampler);
+ cso_single_sampler_done(p->cso);
+
+ arr[0] = p->view;
+ cso_set_fragment_sampler_views(p->cso, 3, arr);
+
+ cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][0]); /* passvs */
+ cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][3]);
+
+ pp_filter_draw(p);
+ pp_filter_end_pass(p);
+ pipe_sampler_view_reference(&arr[1], NULL);
+
+
+ /* Third pass: smoothed edges */
+ /* Sampler order: colormap, blendmap (wtf compiler) */
+ pp_filter_setup_in(p, ppq->inner_tmp[1]);
+ pp_filter_setup_out(p, out);
+
+ pp_filter_set_fb(p);
+
+ /* Blit the input to the output */
+ util_blit_pixels(p->blitctx, in, 0, 0, 0,
+ w, h, 0, p->framebuffer.cbufs[0],
+ 0, 0, w, h, 0, PIPE_TEX_MIPFILTER_NEAREST);
+
+ u_sampler_view_default_template(&v_tmp, in, in->format);
+ arr[0] = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);
+
+ cso_single_sampler(p->cso, 0, &p->sampler_point);
+ cso_single_sampler(p->cso, 1, &p->sampler_point);
+ cso_single_sampler_done(p->cso);
+
+ arr[1] = p->view;
+ cso_set_fragment_sampler_views(p->cso, 2, arr);
+
+ cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]); /* offsetvs */
+ cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][4]);
+
+ p->blend.rt[0].blend_enable = 1;
+ cso_set_blend(p->cso, &p->blend);
+
+ pp_filter_draw(p);
+ pp_filter_end_pass(p);
+ pipe_sampler_view_reference(&arr[0], NULL);
+
+ p->blend.rt[0].blend_enable = 0;
+ p->framebuffer.zsbuf = NULL;
+}
+
+/** The init function of the MLAA filter. */
+static void
+pp_jimenezmlaa_init_run(struct pp_queue_t *ppq, unsigned int n,
+ unsigned int val, bool iscolor)
+{
+
+ struct pipe_box box;
+ struct pipe_resource res;
+
+ char *tmp_text = calloc(sizeof(blend2fs_1) + sizeof(blend2fs_2) +
+ IMM_SPACE, sizeof(char));
+
+ constbuf = pipe_buffer_create(ppq->p->screen, PIPE_BIND_CONSTANT_BUFFER,
+ PIPE_USAGE_STATIC, sizeof(constants));
+ if (!constbuf) {
+ pp_debug("Failed to allocate constant buffer\n");
+ return;
+ }
+
+
+ pp_debug("mlaa: using %u max search steps\n", val);
+
+ if (!tmp_text) {
+ pp_debug("Failed to allocate shader space\n");
+ return;
+ }
+ sprintf(tmp_text, "%s"
+ "IMM FLT32 { %.8f, 0.0000, 0.0000, 0.0000}\n"
+ "%s\n", blend2fs_1, (float) val, blend2fs_2);
+
+ memset(&res, 0, sizeof(res));
+
+ res.target = PIPE_TEXTURE_2D;
+ res.format = PIPE_FORMAT_R8G8_UNORM;
+ res.width0 = res.height0 = 165;
+ res.bind = PIPE_BIND_SAMPLER_VIEW;
+ res.usage = PIPE_USAGE_STATIC;
+ res.depth0 = res.array_size = res.nr_samples = 1;
+
+ if (!ppq->p->screen->is_format_supported(ppq->p->screen, res.format,
+ res.target, 1, res.bind))
+ pp_debug("Areamap format not supported\n");
+
+ areamaptex = ppq->p->screen->resource_create(ppq->p->screen, &res);
+ u_box_2d(0, 0, 165, 165, &box);
+
+ ppq->p->pipe->transfer_inline_write(ppq->p->pipe, areamaptex, 0,
+ PIPE_TRANSFER_WRITE, &box,
+ areamap, 165 * 2, sizeof(areamap));
+
+
+
+ ppq->shaders[n][1] = pp_tgsi_to_state(ppq->p->pipe, offsetvs, true,
+ "offsetvs");
+ if (iscolor)
+ ppq->shaders[n][2] = pp_tgsi_to_state(ppq->p->pipe, color1fs,
+ false, "color1fs");
+ else
+ ppq->shaders[n][2] = pp_tgsi_to_state(ppq->p->pipe, depth1fs,
+ false, "depth1fs");
+ ppq->shaders[n][3] = pp_tgsi_to_state(ppq->p->pipe, tmp_text, false,
+ "blend2fs");
+ ppq->shaders[n][4] = pp_tgsi_to_state(ppq->p->pipe, neigh3fs, false,
+ "neigh3fs");
+
+ free(tmp_text);
+}
+
+/** Short wrapper to init the depth version. */
+void
+pp_jimenezmlaa_init(struct pp_queue_t *ppq, unsigned int n, unsigned int val)
+{
+
+ pp_jimenezmlaa_init_run(ppq, n, val, false);
+}
+
+/** Short wrapper to init the color version. */
+void
+pp_jimenezmlaa_init_color(struct pp_queue_t *ppq, unsigned int n,
+ unsigned int val)
+{
+
+ pp_jimenezmlaa_init_run(ppq, n, val, true);
+}
+
+/** Short wrapper to run the depth version. */
+void
+pp_jimenezmlaa(struct pp_queue_t *ppq, struct pipe_resource *in,
+ struct pipe_resource *out, unsigned int n)
+{
+ pp_jimenezmlaa_run(ppq, in, out, n, false);
+}
+
+/** Short wrapper to run the color version. */
+void
+pp_jimenezmlaa_color(struct pp_queue_t *ppq, struct pipe_resource *in,
+ struct pipe_resource *out, unsigned int n)
+{
+ pp_jimenezmlaa_run(ppq, in, out, n, true);
+}
diff --git a/src/gallium/auxiliary/postprocess/pp_mlaa.h b/src/gallium/auxiliary/postprocess/pp_mlaa.h
new file mode 100644
index 00000000000..9972d59c6a6
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_mlaa.h
@@ -0,0 +1,342 @@
+/**
+ * Copyright (C) 2010 Jorge Jimenez ([email protected])
+ * Copyright (C) 2010 Belen Masia ([email protected])
+ * Copyright (C) 2010 Jose I. Echevarria ([email protected])
+ * Copyright (C) 2010 Fernando Navarro ([email protected])
+ * Copyright (C) 2010 Diego Gutierrez ([email protected])
+ * Copyright (C) 2011 Lauri Kasanen ([email protected])
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the following statement:
+ *
+ * "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia,
+ * Jose I. Echevarria, Fernando Navarro and Diego Gutierrez."
+ *
+ * Only for use in the Mesa project, this point 2 is filled by naming the
+ * technique Jimenez's MLAA in the Mesa config options.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the copyright holders.
+ */
+
+#ifndef PP_MLAA_H
+#define PP_MLAA_H
+
+#include "postprocess/pp_mlaa_areamap.h"
+
+static const char depth1fs[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL IN[1], GENERIC[10], PERSPECTIVE\n"
+ "DCL IN[2], GENERIC[11], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL TEMP[0..2]\n"
+ "IMM FLT32 { 0.0030, 0.0000, 1.0000, 0.0000}\n"
+ " 0: TEX TEMP[0].x, IN[1].xyyy, SAMP[0], 2D\n"
+ " 1: MOV TEMP[1].x, TEMP[0].xxxx\n"
+ " 2: TEX TEMP[0].x, IN[1].zwww, SAMP[0], 2D\n"
+ " 3: MOV TEMP[1].y, TEMP[0].xxxx\n"
+ " 4: TEX TEMP[0].x, IN[2].xyyy, SAMP[0], 2D\n"
+ " 5: MOV TEMP[1].z, TEMP[0].xxxx\n"
+ " 6: TEX TEMP[0].x, IN[2].zwww, SAMP[0], 2D\n"
+ " 7: MOV TEMP[1].w, TEMP[0].xxxx\n"
+ " 8: TEX TEMP[0].x, IN[0].xyyy, SAMP[0], 2D\n"
+ " 9: ADD TEMP[2], TEMP[0].xxxx, -TEMP[1]\n"
+ " 10: ABS TEMP[0], TEMP[2]\n"
+ " 11: SGE TEMP[2], TEMP[0], IMM[0].xxxx\n"
+ " 12: DP4 TEMP[0].x, TEMP[2], IMM[0].zzzz\n"
+ " 13: SEQ TEMP[1].x, TEMP[0].xxxx, IMM[0].yyyy\n"
+ " 14: IF TEMP[1].xxxx :16\n"
+ " 15: KILP\n"
+ " 16: ENDIF\n"
+ " 17: MOV OUT[0], TEMP[2]\n"
+ " 18: END\n";
+
+
+static const char color1fs[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL IN[1], GENERIC[10], PERSPECTIVE\n"
+ "DCL IN[2], GENERIC[11], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL TEMP[0..2]\n"
+ "IMM FLT32 { 0.2126, 0.7152, 0.0722, 0.1000}\n"
+ "IMM FLT32 { 1.0000, 0.0000, 0.0000, 0.0000}\n"
+ " 0: TEX TEMP[1].xyz, IN[1].xyyy, SAMP[0], 2D\n"
+ " 1: DP3 TEMP[0].x, TEMP[1].xyzz, IMM[0]\n"
+ " 2: TEX TEMP[1].xyz, IN[1].zwww, SAMP[0], 2D\n"
+ " 3: DP3 TEMP[0].y, TEMP[1].xyzz, IMM[0].xyzz\n"
+ " 4: TEX TEMP[1].xyz, IN[2].xyyy, SAMP[0], 2D\n"
+ " 5: DP3 TEMP[0].z, TEMP[1].xyzz, IMM[0].xyzz\n"
+ " 6: TEX TEMP[1].xyz, IN[2].zwww, SAMP[0], 2D\n"
+ " 7: DP3 TEMP[0].w, TEMP[1].xyzz, IMM[0].xyzz\n"
+ " 8: TEX TEMP[1].xyz, IN[0].xyyy, SAMP[0], 2D\n"
+ " 9: DP3 TEMP[2].x, TEMP[1].xyzz, IMM[0].xyzz\n"
+ " 10: ADD TEMP[1], TEMP[2].xxxx, -TEMP[0]\n"
+ " 11: ABS TEMP[0], TEMP[1]\n"
+ " 12: SGE TEMP[2], TEMP[0], IMM[0].wwww\n"
+ " 13: DP4 TEMP[0].x, TEMP[2], IMM[1].xxxx\n"
+ " 14: SEQ TEMP[1].x, TEMP[0].xxxx, IMM[1].yyyy\n"
+ " 15: IF TEMP[1].xxxx :17\n"
+ " 16: KILP\n"
+ " 17: ENDIF\n"
+ " 18: MOV OUT[0], TEMP[2]\n"
+ " 19: END\n";
+
+
+static const char neigh3fs[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL IN[1], GENERIC[10], PERSPECTIVE\n"
+ "DCL IN[2], GENERIC[11], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL SAMP[1]\n"
+ "DCL TEMP[0..8]\n"
+ "IMM FLT32 { 1.0000, 0.00001, 0.0000, 0.0000}\n"
+ " 0: TEX TEMP[0], IN[0].xyyy, SAMP[1], 2D\n"
+ " 1: MOV TEMP[1].x, TEMP[0].xxxx\n"
+ " 2: TEX TEMP[2].y, IN[2].zwww, SAMP[1], 2D\n"
+ " 3: MOV TEMP[1].y, TEMP[2].yyyy\n"
+ " 4: MOV TEMP[1].z, TEMP[0].zzzz\n"
+ " 5: TEX TEMP[1].w, IN[2].xyyy, SAMP[1], 2D\n"
+ " 6: MUL TEMP[4], TEMP[1], TEMP[1]\n"
+ " 7: MUL TEMP[5], TEMP[4], TEMP[1]\n"
+ " 8: DP4 TEMP[1].x, TEMP[5], IMM[0].xxxx\n"
+ " 9: SLT TEMP[4].x, TEMP[1].xxxx, IMM[0].yyyy\n"
+ " 10: IF TEMP[4].xxxx :12\n"
+ " 11: KILP\n"
+ " 12: ENDIF\n"
+ " 13: TEX TEMP[4], IN[0].xyyy, SAMP[0], 2D\n"
+ " 14: TEX TEMP[6], IN[1].zwww, SAMP[0], 2D\n"
+ " 15: ADD TEMP[7].x, IMM[0].xxxx, -TEMP[0].xxxx\n"
+ " 16: MUL TEMP[8], TEMP[4], TEMP[7].xxxx\n"
+ " 17: MAD TEMP[7], TEMP[6], TEMP[0].xxxx, TEMP[8]\n"
+ " 18: MUL TEMP[6], TEMP[7], TEMP[5].xxxx\n"
+ " 19: TEX TEMP[7], IN[2].zwww, SAMP[0], 2D\n"
+ " 20: ADD TEMP[8].x, IMM[0].xxxx, -TEMP[2].yyyy\n"
+ " 21: MUL TEMP[3], TEMP[4], TEMP[8].xxxx\n"
+ " 22: MAD TEMP[8], TEMP[7], TEMP[2].yyyy, TEMP[3]\n"
+ " 23: MAD TEMP[2], TEMP[8], TEMP[5].yyyy, TEMP[6]\n"
+ " 24: TEX TEMP[6], IN[1].xyyy, SAMP[0], 2D\n"
+ " 25: ADD TEMP[7].x, IMM[0].xxxx, -TEMP[0].zzzz\n"
+ " 26: MUL TEMP[8], TEMP[4], TEMP[7].xxxx\n"
+ " 27: MAD TEMP[7], TEMP[6], TEMP[0].zzzz, TEMP[8]\n"
+ " 28: MAD TEMP[0], TEMP[7], TEMP[5].zzzz, TEMP[2]\n"
+ " 29: TEX TEMP[2], IN[2].xyyy, SAMP[0], 2D\n"
+ " 30: ADD TEMP[6].x, IMM[0].xxxx, -TEMP[1].wwww\n"
+ " 31: MUL TEMP[7], TEMP[4], TEMP[6].xxxx\n"
+ " 32: MAD TEMP[4], TEMP[2], TEMP[1].wwww, TEMP[7]\n"
+ " 33: MAD TEMP[2], TEMP[4], TEMP[5].wwww, TEMP[0]\n"
+ " 34: RCP TEMP[0].x, TEMP[1].xxxx\n"
+ " 35: MUL OUT[0], TEMP[2], TEMP[0].xxxx\n"
+ " 36: END\n";
+
+
+static const char offsetvs[] = "VERT\n"
+ "DCL IN[0]\n"
+ "DCL IN[1]\n"
+ "DCL OUT[0], POSITION\n"
+ "DCL OUT[1], GENERIC[0]\n"
+ "DCL OUT[2], GENERIC[10]\n"
+ "DCL OUT[3], GENERIC[11]\n"
+ "DCL CONST[0]\n"
+ "IMM FLT32 { 1.0000, 0.0000, -1.0000, 0.0000}\n"
+ " 0: MOV OUT[0], IN[0]\n"
+ " 1: MOV OUT[1], IN[1]\n"
+ " 2: MAD OUT[2], CONST[0].xyxy, IMM[0].zyyz, IN[1].xyxy\n"
+ " 3: MAD OUT[3], CONST[0].xyxy, IMM[0].xyyx, IN[1].xyxy\n"
+ " 4: END\n";
+
+
+static const char blend2fs_1[] = "FRAG\n"
+ "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
+ "DCL IN[0], GENERIC[0], PERSPECTIVE\n"
+ "DCL OUT[0], COLOR\n"
+ "DCL SAMP[0]\n"
+ "DCL SAMP[1]\n"
+ "DCL SAMP[2]\n"
+ "DCL CONST[0]\n"
+ "DCL TEMP[0..6]\n"
+ "IMM FLT32 { 0.0000, -0.2500, 0.00609756, 0.5000}\n"
+ "IMM FLT32 { -1.5000, -2.0000, 0.9000, 1.5000}\n"
+ "IMM FLT32 { 2.0000, 1.0000, 4.0000, 33.0000}\n";
+
+static const char blend2fs_2[] =
+ " 0: MOV TEMP[0], IMM[0].xxxx\n"
+ " 1: TEX TEMP[1], IN[0].xyyy, SAMP[1], 2D\n"
+ " 2: MOV TEMP[2].x, TEMP[1]\n"
+ " 3: SNE TEMP[3].x, TEMP[1].yyyy, IMM[0].xxxx\n"
+ " 4: IF TEMP[3].xxxx :76\n"
+ " 5: MOV TEMP[1].xy, IN[0].xyxx\n"
+ " 6: MOV TEMP[4].x, IMM[1].xxxx\n"
+ " 7: BGNLOOP :24\n"
+ " 8: MUL TEMP[5].x, IMM[1].yyyy, IMM[3].xxxx\n"
+ " 9: SLE TEMP[6].x, TEMP[4].xxxx, TEMP[5].xxxx\n"
+ " 10: IF TEMP[6].xxxx :12\n"
+ " 11: BRK\n"
+ " 12: ENDIF\n"
+ " 13: MOV TEMP[4].y, IMM[0].xxxx\n"
+ " 14: MAD TEMP[3].xyz, CONST[0].xyyy, TEMP[4].xyyy, TEMP[1].xyyy\n"
+ " 15: MOV TEMP[3].w, IMM[0].xxxx\n"
+ " 16: TXL TEMP[5], TEMP[3], SAMP[2], 2D\n"
+ " 17: MOV TEMP[3].x, TEMP[5].yyyy\n"
+ " 18: SLT TEMP[6].x, TEMP[5].yyyy, IMM[1].zzzz\n"
+ " 19: IF TEMP[6].xxxx :21\n"
+ " 20: BRK\n"
+ " 21: ENDIF\n"
+ " 22: ADD TEMP[6].x, TEMP[4].xxxx, IMM[1].yyyy\n"
+ " 23: MOV TEMP[4].x, TEMP[6].xxxx\n"
+ " 24: ENDLOOP :7\n"
+ " 25: ADD TEMP[1].x, TEMP[4].xxxx, IMM[1].wwww\n"
+ " 26: MAD TEMP[6].x, -IMM[2].xxxx, TEMP[3].xxxx, TEMP[1].xxxx\n"
+ " 27: MUL TEMP[1].x, IMM[1].yyyy, IMM[3].xxxx\n"
+ " 28: MAX TEMP[4].x, TEMP[6].xxxx, TEMP[1].xxxx\n"
+ " 29: MOV TEMP[1].x, TEMP[4].xxxx\n"
+ " 30: MOV TEMP[3].xy, IN[0].xyxx\n"
+ " 31: MOV TEMP[5].x, IMM[1].wwww\n"
+ " 32: BGNLOOP :49\n"
+ " 33: MUL TEMP[6].x, IMM[2].xxxx, IMM[3].xxxx\n"
+ " 34: SGE TEMP[4].x, TEMP[5].xxxx, TEMP[6].xxxx\n"
+ " 35: IF TEMP[4].xxxx :37\n"
+ " 36: BRK\n"
+ " 37: ENDIF\n"
+ " 38: MOV TEMP[5].y, IMM[0].xxxx\n"
+ " 39: MAD TEMP[4].xyz, CONST[0].xyyy, TEMP[5].xyyy, TEMP[3].xyyy\n"
+ " 40: MOV TEMP[4].w, IMM[0].xxxx\n"
+ " 41: TXL TEMP[6].xy, TEMP[4], SAMP[2], 2D\n"
+ " 42: MOV TEMP[4].x, TEMP[6].yyyy\n"
+ " 43: SLT TEMP[0].x, TEMP[6].yyyy, IMM[1].zzzz\n"
+ " 44: IF TEMP[0].xxxx :46\n"
+ " 45: BRK\n"
+ " 46: ENDIF\n"
+ " 47: ADD TEMP[6].x, TEMP[5].xxxx, IMM[2].xxxx\n"
+ " 48: MOV TEMP[5].x, TEMP[6].xxxx\n"
+ " 49: ENDLOOP :32\n"
+ " 50: ADD TEMP[3].x, TEMP[5].xxxx, IMM[1].xxxx\n"
+ " 51: MAD TEMP[5].x, IMM[2].xxxx, TEMP[4].xxxx, TEMP[3].xxxx\n"
+ " 52: MUL TEMP[3].x, IMM[2].xxxx, IMM[3].xxxx\n"
+ " 53: MIN TEMP[4].x, TEMP[5].xxxx, TEMP[3].xxxx\n"
+ " 54: MOV TEMP[3].x, TEMP[1].xxxx\n"
+ " 55: MOV TEMP[3].y, TEMP[4].xxxx\n"
+ " 56: MOV TEMP[5].yw, IMM[0].yyyy\n"
+ " 57: MOV TEMP[5].x, TEMP[1].xxxx\n"
+ " 58: ADD TEMP[1].x, TEMP[4].xxxx, IMM[2].yyyy\n"
+ " 59: MOV TEMP[5].z, TEMP[1].xxxx\n"
+ " 60: MAD TEMP[1], TEMP[5], CONST[0].xyxy, IN[0].xyxy\n"
+ " 61: MOV TEMP[4], TEMP[1].xyyy\n"
+ " 62: MOV TEMP[4].w, IMM[0].xxxx\n"
+ " 63: TXL TEMP[5].x, TEMP[4], SAMP[2], 2D\n"
+ " 64: MOV TEMP[4].x, TEMP[5].xxxx\n"
+ " 65: MOV TEMP[5], TEMP[1].zwww\n"
+ " 66: MOV TEMP[5].w, IMM[0].xxxx\n"
+ " 67: TXL TEMP[1].x, TEMP[5], SAMP[2], 2D\n"
+ " 68: MOV TEMP[4].y, TEMP[1].xxxx\n"
+ " 69: MUL TEMP[5].xy, IMM[2].zzzz, TEMP[4].xyyy\n"
+ " 70: ROUND TEMP[1].xy, TEMP[5].xyyy\n"
+ " 71: ABS TEMP[4].xy, TEMP[3].xyyy\n"
+ " 72: MAD TEMP[3].xy, IMM[2].wwww, TEMP[1].xyyy, TEMP[4].xyyy\n"
+ " 73: MUL TEMP[5].xyz, TEMP[3].xyyy, IMM[0].zzzz\n"
+ " 74: MOV TEMP[5].w, IMM[0].xxxx\n"
+ " 75: TXL TEMP[0].xy, TEMP[5], SAMP[0], 2D\n"
+ " 76: ENDIF\n"
+ " 77: SNE TEMP[1].x, TEMP[2].xxxx, IMM[0].xxxx\n"
+ " 78: IF TEMP[1].xxxx :151\n"
+ " 79: MOV TEMP[1].xy, IN[0].xyxx\n"
+ " 80: MOV TEMP[3].x, IMM[1].xxxx\n"
+ " 81: BGNLOOP :98\n"
+ " 82: MUL TEMP[4].x, IMM[1].yyyy, IMM[3].xxxx\n"
+ " 83: SLE TEMP[5].x, TEMP[3].xxxx, TEMP[4].xxxx\n"
+ " 84: IF TEMP[5].xxxx :86\n"
+ " 85: BRK\n"
+ " 86: ENDIF\n"
+ " 87: MOV TEMP[3].y, IMM[0].xxxx\n"
+ " 88: MAD TEMP[5].xyz, CONST[0].xyyy, TEMP[3].yxxx, TEMP[1].xyyy\n"
+ " 89: MOV TEMP[5].w, IMM[0].xxxx\n"
+ " 90: TXL TEMP[4], TEMP[5], SAMP[2], 2D\n"
+ " 91: MOV TEMP[2].x, TEMP[4].xxxx\n"
+ " 92: SLT TEMP[5].x, TEMP[4].xxxx, IMM[1].zzzz\n"
+ " 93: IF TEMP[5].xxxx :95\n"
+ " 94: BRK\n"
+ " 95: ENDIF\n"
+ " 96: ADD TEMP[4].x, TEMP[3].xxxx, IMM[1].yyyy\n"
+ " 97: MOV TEMP[3].x, TEMP[4].xxxx\n"
+ " 98: ENDLOOP :81\n"
+ " 99: ADD TEMP[1].x, TEMP[3].xxxx, IMM[1].wwww\n"
+ "100: MAD TEMP[6].x, -IMM[2].xxxx, TEMP[2].xxxx, TEMP[1].xxxx\n"
+ "101: MUL TEMP[1].x, IMM[1].yyyy, IMM[3].xxxx\n"
+ "102: MAX TEMP[3].x, TEMP[6].xxxx, TEMP[1].xxxx\n"
+ "103: MOV TEMP[1].x, TEMP[3].xxxx\n"
+ "104: MOV TEMP[2].xy, IN[0].xyxx\n"
+ "105: MOV TEMP[4].x, IMM[1].wwww\n"
+ "106: BGNLOOP :123\n"
+ "107: MUL TEMP[5].x, IMM[2].xxxx, IMM[3].xxxx\n"
+ "108: SGE TEMP[6].x, TEMP[4].xxxx, TEMP[5].xxxx\n"
+ "109: IF TEMP[6].xxxx :111\n"
+ "110: BRK\n"
+ "111: ENDIF\n"
+ "112: MOV TEMP[4].y, IMM[0].xxxx\n"
+ "113: MAD TEMP[5].xyz, CONST[0].xyyy, TEMP[4].yxxx, TEMP[2].xyyy\n"
+ "114: MOV TEMP[5].w, IMM[0].xxxx\n"
+ "115: TXL TEMP[6], TEMP[5], SAMP[2], 2D\n"
+ "116: MOV TEMP[3].x, TEMP[6].xxxx\n"
+ "117: SLT TEMP[5].x, TEMP[6].xxxx, IMM[1].zzzz\n"
+ "118: IF TEMP[5].xxxx :120\n"
+ "119: BRK\n"
+ "120: ENDIF\n"
+ "121: ADD TEMP[6].x, TEMP[4].xxxx, IMM[2].xxxx\n"
+ "122: MOV TEMP[4].x, TEMP[6].xxxx\n"
+ "123: ENDLOOP :106\n"
+ "124: ADD TEMP[2].x, TEMP[4].xxxx, IMM[1].xxxx\n"
+ "125: MAD TEMP[4].x, IMM[2].xxxx, TEMP[3].xxxx, TEMP[2].xxxx\n"
+ "126: MUL TEMP[2].x, IMM[2].xxxx, IMM[3].xxxx\n"
+ "127: MIN TEMP[3].x, TEMP[4].xxxx, TEMP[2].xxxx\n"
+ "128: MOV TEMP[2].x, TEMP[1].xxxx\n"
+ "129: MOV TEMP[2].y, TEMP[3].xxxx\n"
+ "130: MOV TEMP[4].xz, IMM[0].yyyy\n"
+ "131: MOV TEMP[4].y, TEMP[1].xxxx\n"
+ "132: ADD TEMP[1].x, TEMP[3].xxxx, IMM[2].yyyy\n"
+ "133: MOV TEMP[4].w, TEMP[1].xxxx\n"
+ "134: MAD TEMP[1], TEMP[4], CONST[0].xyxy, IN[0].xyxy\n"
+ "135: MOV TEMP[3], TEMP[1].xyyy\n"
+ "136: MOV TEMP[3].w, IMM[0].xxxx\n"
+ "137: TXL TEMP[4].y, TEMP[3], SAMP[2], 2D\n"
+ "138: MOV TEMP[3].x, TEMP[4].yyyy\n"
+ "139: MOV TEMP[4], TEMP[1].zwww\n"
+ "140: MOV TEMP[4].w, IMM[0].xxxx\n"
+ "141: TXL TEMP[1].y, TEMP[4], SAMP[2], 2D\n"
+ "142: MOV TEMP[3].y, TEMP[1].yyyy\n"
+ "143: MUL TEMP[4].xy, IMM[2].zzzz, TEMP[3].xyyy\n"
+ "144: ROUND TEMP[1].xy, TEMP[4].xyyy\n"
+ "145: ABS TEMP[3].xy, TEMP[2].xyyy\n"
+ "146: MAD TEMP[2].xy, IMM[2].wwww, TEMP[1].xyyy, TEMP[3].xyyy\n"
+ "147: MUL TEMP[3].xyz, TEMP[2].xyyy, IMM[0].zzzz\n"
+ "148: MOV TEMP[3].w, IMM[0].xxxx\n"
+ "149: TXL TEMP[1].xy, TEMP[3], SAMP[0], 2D\n"
+ "150: MOV TEMP[0].zw, TEMP[1].yyxy\n"
+ "151: ENDIF\n"
+ "152: MOV OUT[0], TEMP[0]\n"
+ "153: END\n";
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/pp_mlaa_areamap.h b/src/gallium/auxiliary/postprocess/pp_mlaa_areamap.h
new file mode 100644
index 00000000000..1446ff2cdf0
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_mlaa_areamap.h
@@ -0,0 +1,2821 @@
+/**
+ * Copyright (C) 2010 Jorge Jimenez ([email protected])
+ * Copyright (C) 2010 Belen Masia ([email protected])
+ * Copyright (C) 2010 Jose I. Echevarria ([email protected])
+ * Copyright (C) 2010 Fernando Navarro ([email protected])
+ * Copyright (C) 2010 Diego Gutierrez ([email protected])
+ * Copyright (C) 2011 Lauri Kasanen ([email protected])
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the following statement:
+ *
+ * "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia,
+ * Jose I. Echevarria, Fernando Navarro and Diego Gutierrez."
+ *
+ * Only for use in the Mesa project, this point 2 is filled by naming the
+ * technique Jimenez's MLAA in the Mesa config options.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the copyright holders.
+ */
+
+#ifndef PP_MLAA_AREAMAP_H
+#define PP_MLAA_AREAMAP_H
+
+static const unsigned char areamap[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 85, 0, 31, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0,
+ 31, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 51,
+ 0, 21, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 51, 0, 21, 0, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 102, 0, 63, 0, 36, 0, 15, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 0,
+ 63, 0, 36, 0, 15, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 72,
+ 0, 47, 0, 28, 0, 12, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 72, 0, 47, 0, 28, 0, 12, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 109, 0, 79, 0, 56, 0, 38, 0, 23, 0, 10, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 0,
+ 79, 0, 56, 0, 38, 0, 23, 0, 10, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 85,
+ 0, 63, 0, 46, 0, 31, 0, 19, 0, 9, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 85, 0, 63, 0, 46, 0, 31, 0, 19, 0,
+ 9, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 113, 0, 89, 0, 69, 0, 53, 0, 39, 0, 27, 0, 17,
+ 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 0,
+ 89, 0, 69, 0, 53, 0, 39, 0, 27, 0, 17, 0, 7, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 0, 92,
+ 0, 74, 0, 58, 0, 45, 0, 34, 0, 23, 0, 15, 0, 7, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 114, 0, 92, 0, 74, 0, 58, 0, 45, 0, 34, 0,
+ 23, 0, 15, 0, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 115, 0, 95, 0, 78, 0, 63, 0, 51, 0, 39, 0, 30,
+ 0, 21, 0, 13, 0, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 0,
+ 95, 0, 78, 0, 63, 0, 51, 0, 39, 0, 30, 0, 21, 0, 13, 0, 6, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 98,
+ 0, 81, 0, 68, 0, 55, 0, 44, 0, 35, 0, 26, 0, 19, 0, 12, 0, 5, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 98, 0, 81, 0, 68, 0, 55, 0, 44, 0,
+ 35, 0, 26, 0, 19, 0, 12, 0, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 117, 0, 100, 0, 85, 0, 71, 0, 60, 0, 49, 0, 40,
+ 0, 31, 0, 24, 0, 17, 0, 11, 0, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0,
+ 100, 0, 85, 0, 71, 0, 60, 0, 49, 0, 40, 0, 31, 0, 24, 0, 17, 0, 11, 0,
+ 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, 102,
+ 0, 87, 0, 75, 0, 63, 0, 53, 0, 44, 0, 36, 0, 28, 0, 22, 0, 15, 0, 10,
+ 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, 102, 0, 87, 0, 75, 0, 63, 0, 53, 0,
+ 44, 0, 36, 0, 28, 0, 22, 0, 15, 0, 10, 0, 4, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 119, 0, 103, 0, 89, 0, 77, 0, 67, 0, 57, 0, 48,
+ 0, 40, 0, 33, 0, 26, 0, 20, 0, 14, 0, 9, 0, 4, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0,
+ 103, 0, 89, 0, 77, 0, 67, 0, 57, 0, 48, 0, 40, 0, 33, 0, 26, 0, 20, 0,
+ 14, 0, 9, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 105,
+ 0, 92, 0, 80, 0, 70, 0, 60, 0, 52, 0, 44, 0, 37, 0, 30, 0, 24, 0, 18,
+ 0, 13, 0, 8, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 105, 0, 92, 0, 80, 0, 70, 0, 60, 0,
+ 52, 0, 44, 0, 37, 0, 30, 0, 24, 0, 18, 0, 13, 0, 8, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 120, 0, 106, 0, 93, 0, 82, 0, 72, 0, 63, 0, 55,
+ 0, 47, 0, 40, 0, 34, 0, 28, 0, 22, 0, 17, 0, 12, 0, 8, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0,
+ 106, 0, 93, 0, 82, 0, 72, 0, 63, 0, 55, 0, 47, 0, 40, 0, 34, 0, 28, 0,
+ 22, 0, 17, 0, 12, 0, 8, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 107,
+ 0, 95, 0, 85, 0, 75, 0, 66, 0, 58, 0, 51, 0, 44, 0, 37, 0, 31, 0, 26,
+ 0, 21, 0, 16, 0, 11, 0, 7, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 107, 0, 95, 0, 85, 0, 75, 0, 66, 0,
+ 58, 0, 51, 0, 44, 0, 37, 0, 31, 0, 26, 0, 21, 0, 16, 0, 11, 0, 7, 0,
+ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 120, 0, 108, 0, 97, 0, 86, 0, 77, 0, 69, 0, 61,
+ 0, 53, 0, 47, 0, 40, 0, 35, 0, 29, 0, 24, 0, 19, 0, 15, 0, 11, 0, 7,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0,
+ 108, 0, 97, 0, 86, 0, 77, 0, 69, 0, 61, 0, 53, 0, 47, 0, 40, 0, 35, 0,
+ 29, 0, 24, 0, 19, 0, 15, 0, 11, 0, 7, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 109,
+ 0, 98, 0, 88, 0, 79, 0, 71, 0, 63, 0, 56, 0, 50, 0, 43, 0, 38, 0, 32,
+ 0, 27, 0, 23, 0, 18, 0, 14, 0, 10, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 109, 0, 98, 0, 88, 0, 79, 0, 71, 0,
+ 63, 0, 56, 0, 50, 0, 43, 0, 38, 0, 32, 0, 27, 0, 23, 0, 18, 0, 14, 0,
+ 10, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 121, 0, 110, 0, 99, 0, 90, 0, 81, 0, 73, 0, 66,
+ 0, 59, 0, 52, 0, 46, 0, 41, 0, 35, 0, 30, 0, 26, 0, 21, 0, 17, 0, 13,
+ 0, 10, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 110, 0, 99, 0, 90, 0, 81, 0, 73, 0, 66, 0, 59, 0, 52, 0, 46, 0, 41, 0,
+ 35, 0, 30, 0, 26, 0, 21, 0, 17, 0, 13, 0, 10, 0, 6, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 110,
+ 0, 100, 0, 91, 0, 83, 0, 75, 0, 68, 0, 61, 0, 55, 0, 49, 0, 43, 0, 38,
+ 0, 33, 0, 29, 0, 24, 0, 20, 0, 16, 0, 13, 0, 9, 0, 6, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 110, 0, 100, 0, 91, 0, 83, 0, 75, 0,
+ 68, 0, 61, 0, 55, 0, 49, 0, 43, 0, 38, 0, 33, 0, 29, 0, 24, 0, 20, 0,
+ 16, 0, 13, 0, 9, 0, 6, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 121, 0, 111, 0, 102, 0, 93, 0, 85, 0, 77, 0, 70,
+ 0, 63, 0, 57, 0, 51, 0, 46, 0, 41, 0, 36, 0, 31, 0, 27, 0, 23, 0, 19,
+ 0, 15, 0, 12, 0, 9, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 111, 0, 102, 0, 93, 0, 85, 0, 77, 0, 70, 0, 63, 0, 57, 0, 51, 0, 46, 0,
+ 41, 0, 36, 0, 31, 0, 27, 0, 23, 0, 19, 0, 15, 0, 12, 0, 9, 0, 5, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 112,
+ 0, 102, 0, 94, 0, 86, 0, 79, 0, 72, 0, 65, 0, 59, 0, 54, 0, 48, 0, 43,
+ 0, 38, 0, 34, 0, 30, 0, 26, 0, 22, 0, 18, 0, 15, 0, 11, 0, 8, 0, 5,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 112, 0, 102, 0, 94, 0, 86, 0, 79, 0,
+ 72, 0, 65, 0, 59, 0, 54, 0, 48, 0, 43, 0, 38, 0, 34, 0, 30, 0, 26, 0,
+ 22, 0, 18, 0, 15, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 122, 0, 112, 0, 103, 0, 95, 0, 87, 0, 80, 0, 74,
+ 0, 67, 0, 61, 0, 56, 0, 51, 0, 46, 0, 41, 0, 36, 0, 32, 0, 28, 0, 24,
+ 0, 21, 0, 17, 0, 14, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 112, 0, 103, 0, 95, 0, 87, 0, 80, 0, 74, 0, 67, 0, 61, 0, 56, 0, 51, 0,
+ 46, 0, 41, 0, 36, 0, 32, 0, 28, 0, 24, 0, 21, 0, 17, 0, 14, 0, 11, 0,
+ 8, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 113,
+ 0, 104, 0, 96, 0, 89, 0, 82, 0, 75, 0, 69, 0, 63, 0, 58, 0, 53, 0, 48,
+ 0, 43, 0, 39, 0, 35, 0, 31, 0, 27, 0, 23, 0, 20, 0, 17, 0, 13, 0, 10,
+ 0, 7, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 113, 0, 104, 0, 96, 0, 89, 0, 82, 0,
+ 75, 0, 69, 0, 63, 0, 58, 0, 53, 0, 48, 0, 43, 0, 39, 0, 35, 0, 31, 0,
+ 27, 0, 23, 0, 20, 0, 17, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 122, 0, 113, 0, 105, 0, 97, 0, 90, 0, 83, 0, 77,
+ 0, 71, 0, 65, 0, 60, 0, 55, 0, 50, 0, 45, 0, 41, 0, 37, 0, 33, 0, 29,
+ 0, 26, 0, 22, 0, 19, 0, 16, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 113, 0, 105, 0, 97, 0, 90, 0, 83, 0, 77, 0, 71, 0, 65, 0, 60, 0, 55, 0,
+ 50, 0, 45, 0, 41, 0, 37, 0, 33, 0, 29, 0, 26, 0, 22, 0, 19, 0, 16, 0,
+ 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 114,
+ 0, 106, 0, 98, 0, 91, 0, 85, 0, 78, 0, 72, 0, 67, 0, 62, 0, 57, 0, 52,
+ 0, 47, 0, 43, 0, 39, 0, 35, 0, 31, 0, 28, 0, 24, 0, 21, 0, 18, 0, 15,
+ 0, 12, 0, 10, 0, 7, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 114, 0, 106, 0, 98, 0, 91, 0, 85, 0,
+ 78, 0, 72, 0, 67, 0, 62, 0, 57, 0, 52, 0, 47, 0, 43, 0, 39, 0, 35, 0,
+ 31, 0, 28, 0, 24, 0, 21, 0, 18, 0, 15, 0, 12, 0, 10, 0, 7, 0, 4, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 114, 0, 106, 0, 99, 0, 92, 0, 86, 0, 80,
+ 0, 74, 0, 68, 0, 63, 0, 58, 0, 54, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34,
+ 0, 30, 0, 27, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 9, 0, 7, 0, 4,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 114, 0, 106, 0, 99, 0, 92, 0, 86, 0, 80, 0, 74, 0, 68, 0, 63, 0, 58, 0,
+ 54, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 30, 0, 27, 0, 23, 0, 20, 0,
+ 17, 0, 15, 0, 12, 0, 9, 0, 7, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115,
+ 0, 107, 0, 100, 0, 93, 0, 87, 0, 81, 0, 75, 0, 70, 0, 65, 0, 60, 0, 55,
+ 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 32, 0, 29, 0, 26, 0, 22, 0, 20,
+ 0, 17, 0, 14, 0, 11, 0, 9, 0, 6, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 107, 0, 100, 0, 93, 0, 87, 0,
+ 81, 0, 75, 0, 70, 0, 65, 0, 60, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0,
+ 36, 0, 32, 0, 29, 0, 26, 0, 22, 0, 20, 0, 17, 0, 14, 0, 11, 0, 9, 0,
+ 6, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 108, 0, 101, 0, 94, 0, 88, 0, 82,
+ 0, 77, 0, 71, 0, 66, 0, 62, 0, 57, 0, 53, 0, 49, 0, 45, 0, 41, 0, 37,
+ 0, 34, 0, 31, 0, 28, 0, 25, 0, 22, 0, 19, 0, 16, 0, 13, 0, 11, 0, 8,
+ 0, 6, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 115, 0, 108, 0, 101, 0, 94, 0, 88, 0, 82, 0, 77, 0, 71, 0, 66, 0, 62, 0,
+ 57, 0, 53, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 31, 0, 28, 0, 25, 0,
+ 22, 0, 19, 0, 16, 0, 13, 0, 11, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115,
+ 0, 108, 0, 102, 0, 95, 0, 89, 0, 83, 0, 78, 0, 73, 0, 68, 0, 63, 0, 59,
+ 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 33, 0, 30, 0, 26, 0, 24,
+ 0, 21, 0, 18, 0, 15, 0, 13, 0, 10, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 108, 0, 102, 0, 95, 0, 89, 0,
+ 83, 0, 78, 0, 73, 0, 68, 0, 63, 0, 59, 0, 55, 0, 51, 0, 47, 0, 43, 0,
+ 39, 0, 36, 0, 33, 0, 30, 0, 26, 0, 24, 0, 21, 0, 18, 0, 15, 0, 13, 0,
+ 10, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 116, 0, 109, 0, 102, 0, 96, 0, 90, 0, 85,
+ 0, 79, 0, 74, 0, 69, 0, 65, 0, 60, 0, 56, 0, 52, 0, 48, 0, 45, 0, 41,
+ 0, 38, 0, 35, 0, 31, 0, 28, 0, 25, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12,
+ 0, 10, 0, 8, 0, 6, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 116, 0, 109, 0, 102, 0, 96, 0, 90, 0, 85, 0, 79, 0, 74, 0, 69, 0, 65, 0,
+ 60, 0, 56, 0, 52, 0, 48, 0, 45, 0, 41, 0, 38, 0, 35, 0, 31, 0, 28, 0,
+ 25, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 10, 0, 8, 0, 6, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63, 0, 85, 0, 95, 0, 102,
+ 0, 106, 0, 109, 0, 111, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0,
+ 119,
+ 0, 119, 0, 120, 0, 120, 0, 120, 0, 121, 0, 121, 0, 121, 0, 121, 0, 122, 0,
+ 122,
+ 0, 122, 0, 122, 0, 122, 0, 123, 0, 123, 0, 123, 0, 123, 0, 123, 0, 62, 0,
+ 63,
+ 0, 85, 0, 95, 0, 102, 0, 106, 0, 109, 0, 111, 0, 113, 0, 114, 0, 115, 0,
+ 116,
+ 0, 117, 0, 118, 0, 119, 0, 119, 0, 120, 0, 120, 0, 120, 0, 121, 0, 121, 0,
+ 121,
+ 0, 121, 0, 122, 0, 122, 0, 122, 0, 122, 0, 122, 0, 123, 0, 123, 0, 123, 0,
+ 123,
+ 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 0, 63, 0, 85, 0, 95, 0, 102, 0, 106,
+ 0, 109, 0, 111, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0, 119, 0,
+ 119,
+ 0, 120, 0, 120, 0, 120, 0, 121, 0, 121, 0, 121, 0, 121, 0, 122, 0, 122, 0,
+ 122,
+ 0, 122, 0, 122, 0, 123, 0, 123, 0, 123, 0, 123, 0, 123, 31, 31, 0, 63, 0,
+ 85,
+ 0, 95, 0, 102, 0, 106, 0, 109, 0, 111, 0, 113, 0, 114, 0, 115, 0, 116, 0,
+ 117,
+ 0, 118, 0, 119, 0, 119, 0, 120, 0, 120, 0, 120, 0, 121, 0, 121, 0, 121, 0,
+ 121,
+ 0, 122, 0, 122, 0, 122, 0, 122, 0, 122, 0, 123, 0, 123, 0, 123, 0, 123, 0,
+ 123,
+ 0, 0, 0, 10, 0, 31, 0, 51, 0, 63, 0, 72, 0, 79, 0, 85, 0, 89, 0, 92,
+ 0, 95, 0, 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106, 0, 107, 0, 108, 0,
+ 109,
+ 0, 110, 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 0, 113, 0, 114, 0, 114, 0,
+ 115,
+ 0, 115, 0, 115, 0, 116, 0, 63, 0, 20, 0, 31, 0, 51, 0, 63, 0, 72, 0, 79,
+ 0, 85, 0, 89, 0, 92, 0, 95, 0, 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106,
+ 0, 107, 0, 108, 0, 109, 0, 110, 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 0,
+ 113,
+ 0, 114, 0, 114, 0, 115, 0, 115, 0, 115, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0,
+ 10, 10, 0, 31, 0, 51, 0, 63, 0, 72, 0, 79, 0, 85, 0, 89, 0, 92, 0, 95,
+ 0, 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106, 0, 107, 0, 108, 0, 109, 0,
+ 110,
+ 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 0, 113, 0, 114, 0, 114, 0, 115, 0,
+ 115,
+ 0, 115, 0, 116, 63, 0, 10, 10, 0, 31, 0, 51, 0, 63, 0, 72, 0, 79, 0, 85,
+ 0, 89, 0, 92, 0, 95, 0, 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106, 0, 107,
+ 0, 108, 0, 109, 0, 110, 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 0, 113, 0,
+ 114,
+ 0, 114, 0, 115, 0, 115, 0, 115, 0, 116, 0, 0, 0, 0, 0, 6, 0, 21, 0, 36,
+ 0, 47, 0, 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81, 0, 85, 0, 87, 0, 89,
+ 0, 92, 0, 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100, 0, 102, 0, 102, 0, 103,
+ 0, 104, 0, 105, 0, 106, 0, 106, 0, 107, 0, 108, 0, 108, 0, 109, 0, 85, 0,
+ 31,
+ 0, 12, 0, 21, 0, 36, 0, 47, 0, 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81,
+ 0, 85, 0, 87, 0, 89, 0, 92, 0, 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100,
+ 0, 102, 0, 102, 0, 103, 0, 104, 0, 105, 0, 106, 0, 106, 0, 107, 0, 108, 0,
+ 108,
+ 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 31, 0, 6, 6, 0, 21, 0, 36, 0, 47,
+ 0, 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81, 0, 85, 0, 87, 0, 89, 0, 92,
+ 0, 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100, 0, 102, 0, 102, 0, 103, 0, 104,
+ 0, 105, 0, 106, 0, 106, 0, 107, 0, 108, 0, 108, 0, 109, 85, 0, 31, 0, 6, 6,
+ 0, 21, 0, 36, 0, 47, 0, 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81, 0, 85,
+ 0, 87, 0, 89, 0, 92, 0, 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100, 0, 102,
+ 0, 102, 0, 103, 0, 104, 0, 105, 0, 106, 0, 106, 0, 107, 0, 108, 0, 108, 0,
+ 109,
+ 0, 0, 0, 0, 0, 0, 0, 4, 0, 15, 0, 28, 0, 38, 0, 46, 0, 53, 0, 58,
+ 0, 63, 0, 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82, 0, 85, 0, 86, 0, 88,
+ 0, 90, 0, 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 0, 100,
+ 0, 101, 0, 102, 0, 102, 0, 95, 0, 51, 0, 21, 0, 8, 0, 15, 0, 28, 0, 38,
+ 0, 46, 0, 53, 0, 58, 0, 63, 0, 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82,
+ 0, 85, 0, 86, 0, 88, 0, 90, 0, 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97,
+ 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0,
+ 51, 0, 21, 0, 4, 4, 0, 15, 0, 28, 0, 38, 0, 46, 0, 53, 0, 58, 0, 63,
+ 0, 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82, 0, 85, 0, 86, 0, 88, 0, 90,
+ 0, 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101,
+ 0, 102, 0, 102, 95, 0, 51, 0, 21, 0, 4, 4, 0, 15, 0, 28, 0, 38, 0, 46,
+ 0, 53, 0, 58, 0, 63, 0, 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82, 0, 85,
+ 0, 86, 0, 88, 0, 90, 0, 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98,
+ 0, 99, 0, 100, 0, 101, 0, 102, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 12, 0, 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55, 0, 60, 0, 63, 0, 67,
+ 0, 70, 0, 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 0, 85, 0, 86, 0, 87,
+ 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 102, 0, 63,
+ 0, 36, 0, 15, 0, 6, 0, 12, 0, 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55,
+ 0, 60, 0, 63, 0, 67, 0, 70, 0, 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83,
+ 0, 85, 0, 86, 0, 87, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95,
+ 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 102, 0, 63, 0, 36, 0, 15, 0, 3, 3, 0, 12,
+ 0, 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55, 0, 60, 0, 63, 0, 67, 0, 70,
+ 0, 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 0, 85, 0, 86, 0, 87, 0, 89,
+ 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 102, 0, 63, 0, 36, 0,
+ 15, 0, 3, 3, 0, 12, 0, 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55, 0, 60,
+ 0, 63, 0, 67, 0, 70, 0, 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 0, 85,
+ 0, 86, 0, 87, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 10, 0, 19, 0, 27, 0, 34,
+ 0, 39, 0, 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63, 0, 66, 0, 69, 0, 71,
+ 0, 73, 0, 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83, 0, 85, 0, 86, 0, 87,
+ 0, 88, 0, 89, 0, 90, 0, 106, 0, 72, 0, 47, 0, 28, 0, 12, 0, 4, 0, 10,
+ 0, 19, 0, 27, 0, 34, 0, 39, 0, 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63,
+ 0, 66, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83,
+ 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0,
+ 72, 0, 47, 0, 28, 0, 12, 0, 2, 2, 0, 10, 0, 19, 0, 27, 0, 34, 0, 39,
+ 0, 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63, 0, 66, 0, 69, 0, 71, 0, 73,
+ 0, 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83, 0, 85, 0, 86, 0, 87, 0, 88,
+ 0, 89, 0, 90, 106, 0, 72, 0, 47, 0, 28, 0, 12, 0, 2, 2, 0, 10, 0, 19,
+ 0, 27, 0, 34, 0, 39, 0, 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63, 0, 66,
+ 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83, 0, 85,
+ 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 9, 0, 17, 0, 23, 0, 30, 0, 35, 0, 40, 0, 44, 0, 48,
+ 0, 52, 0, 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68, 0, 70, 0, 72, 0, 74,
+ 0, 75, 0, 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83, 0, 85, 0, 109, 0, 79,
+ 0, 56, 0, 38, 0, 23, 0, 10, 0, 4, 0, 9, 0, 17, 0, 23, 0, 30, 0, 35,
+ 0, 40, 0, 44, 0, 48, 0, 52, 0, 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68,
+ 0, 70, 0, 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83,
+ 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, 79, 0, 56, 0, 38, 0, 23, 0, 10, 0,
+ 2, 2, 0, 9, 0, 17, 0, 23, 0, 30, 0, 35, 0, 40, 0, 44, 0, 48, 0, 52,
+ 0, 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68, 0, 70, 0, 72, 0, 74, 0, 75,
+ 0, 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83, 0, 85, 109, 0, 79, 0, 56, 0,
+ 38, 0, 23, 0, 10, 0, 2, 2, 0, 9, 0, 17, 0, 23, 0, 30, 0, 35, 0, 40,
+ 0, 44, 0, 48, 0, 52, 0, 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68, 0, 70,
+ 0, 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83, 0, 85,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 7, 0, 15,
+ 0, 21, 0, 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47, 0, 51, 0, 53, 0, 56,
+ 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 72, 0, 74, 0, 75,
+ 0, 77, 0, 78, 0, 79, 0, 111, 0, 85, 0, 63, 0, 46, 0, 31, 0, 19, 0, 9,
+ 0, 4, 0, 7, 0, 15, 0, 21, 0, 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47,
+ 0, 51, 0, 53, 0, 56, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71,
+ 0, 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0,
+ 85, 0, 63, 0, 46, 0, 31, 0, 19, 0, 9, 0, 2, 2, 0, 7, 0, 15, 0, 21,
+ 0, 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47, 0, 51, 0, 53, 0, 56, 0, 59,
+ 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 72, 0, 74, 0, 75, 0, 77,
+ 0, 78, 0, 79, 111, 0, 85, 0, 63, 0, 46, 0, 31, 0, 19, 0, 9, 0, 2, 2,
+ 0, 7, 0, 15, 0, 21, 0, 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47, 0, 51,
+ 0, 53, 0, 56, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 72,
+ 0, 74, 0, 75, 0, 77, 0, 78, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 13, 0, 19, 0, 24, 0, 28, 0, 33,
+ 0, 37, 0, 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55, 0, 57, 0, 59, 0, 61,
+ 0, 63, 0, 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73, 0, 74, 0, 113, 0, 89,
+ 0, 69, 0, 53, 0, 39, 0, 27, 0, 17, 0, 7, 0, 2, 0, 7, 0, 13, 0, 19,
+ 0, 24, 0, 28, 0, 33, 0, 37, 0, 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55,
+ 0, 57, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73,
+ 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 89, 0, 69, 0, 53, 0, 39, 0, 27, 0,
+ 17, 0, 7, 0, 1, 1, 0, 7, 0, 13, 0, 19, 0, 24, 0, 28, 0, 33, 0, 37,
+ 0, 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55, 0, 57, 0, 59, 0, 61, 0, 63,
+ 0, 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73, 0, 74, 113, 0, 89, 0, 69, 0,
+ 53, 0, 39, 0, 27, 0, 17, 0, 7, 0, 1, 1, 0, 7, 0, 13, 0, 19, 0, 24,
+ 0, 28, 0, 33, 0, 37, 0, 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55, 0, 57,
+ 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73, 0, 74,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 6, 0, 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34, 0, 37, 0, 40, 0, 43,
+ 0, 46, 0, 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65,
+ 0, 66, 0, 68, 0, 69, 0, 114, 0, 92, 0, 74, 0, 58, 0, 45, 0, 34, 0, 23,
+ 0, 15, 0, 7, 0, 2, 0, 6, 0, 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34,
+ 0, 37, 0, 40, 0, 43, 0, 46, 0, 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60,
+ 0, 62, 0, 63, 0, 65, 0, 66, 0, 68, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 0,
+ 92, 0, 74, 0, 58, 0, 45, 0, 34, 0, 23, 0, 15, 0, 7, 0, 1, 1, 0, 6,
+ 0, 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34, 0, 37, 0, 40, 0, 43, 0, 46,
+ 0, 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0, 66,
+ 0, 68, 0, 69, 114, 0, 92, 0, 74, 0, 58, 0, 45, 0, 34, 0, 23, 0, 15, 0,
+ 7, 0, 1, 1, 0, 6, 0, 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34, 0, 37,
+ 0, 40, 0, 43, 0, 46, 0, 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62,
+ 0, 63, 0, 65, 0, 66, 0, 68, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 11, 0, 15, 0, 20,
+ 0, 24, 0, 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 51,
+ 0, 53, 0, 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0, 115, 0, 95,
+ 0, 78, 0, 63, 0, 51, 0, 39, 0, 30, 0, 21, 0, 13, 0, 6, 0, 2, 0, 5,
+ 0, 11, 0, 15, 0, 20, 0, 24, 0, 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43,
+ 0, 46, 0, 48, 0, 51, 0, 53, 0, 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63,
+ 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 95, 0, 78, 0, 63, 0, 51, 0, 39, 0,
+ 30, 0, 21, 0, 13, 0, 6, 0, 1, 1, 0, 5, 0, 11, 0, 15, 0, 20, 0, 24,
+ 0, 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 51, 0, 53,
+ 0, 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 115, 0, 95, 0, 78, 0,
+ 63, 0, 51, 0, 39, 0, 30, 0, 21, 0, 13, 0, 6, 0, 1, 1, 0, 5, 0, 11,
+ 0, 15, 0, 20, 0, 24, 0, 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46,
+ 0, 48, 0, 51, 0, 53, 0, 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 5, 0, 10, 0, 14, 0, 18, 0, 22, 0, 26, 0, 29, 0, 32,
+ 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50, 0, 52, 0, 54, 0, 55,
+ 0, 57, 0, 59, 0, 60, 0, 116, 0, 98, 0, 81, 0, 68, 0, 55, 0, 44, 0, 35,
+ 0, 26, 0, 19, 0, 12, 0, 5, 0, 2, 0, 5, 0, 10, 0, 14, 0, 18, 0, 22,
+ 0, 26, 0, 29, 0, 32, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50,
+ 0, 52, 0, 54, 0, 55, 0, 57, 0, 59, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0,
+ 98, 0, 81, 0, 68, 0, 55, 0, 44, 0, 35, 0, 26, 0, 19, 0, 12, 0, 5, 0,
+ 1, 1, 0, 5, 0, 10, 0, 14, 0, 18, 0, 22, 0, 26, 0, 29, 0, 32, 0, 35,
+ 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50, 0, 52, 0, 54, 0, 55, 0, 57,
+ 0, 59, 0, 60, 116, 0, 98, 0, 81, 0, 68, 0, 55, 0, 44, 0, 35, 0, 26, 0,
+ 19, 0, 12, 0, 5, 0, 1, 1, 0, 5, 0, 10, 0, 14, 0, 18, 0, 22, 0, 26,
+ 0, 29, 0, 32, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50, 0, 52,
+ 0, 54, 0, 55, 0, 57, 0, 59, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 9,
+ 0, 13, 0, 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33, 0, 36, 0, 38, 0, 41,
+ 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 56, 0, 117, 0, 100,
+ 0, 85, 0, 71, 0, 60, 0, 49, 0, 40, 0, 31, 0, 24, 0, 17, 0, 11, 0, 5,
+ 0, 2, 0, 4, 0, 9, 0, 13, 0, 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33,
+ 0, 36, 0, 38, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55,
+ 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 100, 0, 85, 0, 71, 0, 60, 0, 49, 0,
+ 40, 0, 31, 0, 24, 0, 17, 0, 11, 0, 5, 0, 1, 1, 0, 4, 0, 9, 0, 13,
+ 0, 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33, 0, 36, 0, 38, 0, 41, 0, 43,
+ 0, 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 56, 117, 0, 100, 0, 85, 0,
+ 71, 0, 60, 0, 49, 0, 40, 0, 31, 0, 24, 0, 17, 0, 11, 0, 5, 0, 1, 1,
+ 0, 4, 0, 9, 0, 13, 0, 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33, 0, 36,
+ 0, 38, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 56,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 8, 0, 12, 0, 16, 0, 19, 0, 23,
+ 0, 26, 0, 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47,
+ 0, 49, 0, 51, 0, 52, 0, 118, 0, 102, 0, 87, 0, 75, 0, 63, 0, 53, 0, 44,
+ 0, 36, 0, 28, 0, 22, 0, 15, 0, 10, 0, 4, 0, 2, 0, 4, 0, 8, 0, 12,
+ 0, 16, 0, 19, 0, 23, 0, 26, 0, 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41,
+ 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 0,
+ 102, 0, 87, 0, 75, 0, 63, 0, 53, 0, 44, 0, 36, 0, 28, 0, 22, 0, 15, 0,
+ 10, 0, 4, 0, 1, 1, 0, 4, 0, 8, 0, 12, 0, 16, 0, 19, 0, 23, 0, 26,
+ 0, 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49,
+ 0, 51, 0, 52, 118, 0, 102, 0, 87, 0, 75, 0, 63, 0, 53, 0, 44, 0, 36, 0,
+ 28, 0, 22, 0, 15, 0, 10, 0, 4, 0, 1, 1, 0, 4, 0, 8, 0, 12, 0, 16,
+ 0, 19, 0, 23, 0, 26, 0, 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41, 0, 43,
+ 0, 45, 0, 47, 0, 49, 0, 51, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 4, 0, 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24, 0, 27, 0, 30, 0, 32,
+ 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 48, 0, 119, 0, 103,
+ 0, 89, 0, 77, 0, 67, 0, 57, 0, 48, 0, 40, 0, 33, 0, 26, 0, 20, 0, 14,
+ 0, 9, 0, 4, 0, 2, 0, 4, 0, 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24,
+ 0, 27, 0, 30, 0, 32, 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47,
+ 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 103, 0, 89, 0, 77, 0, 67, 0, 57, 0,
+ 48, 0, 40, 0, 33, 0, 26, 0, 20, 0, 14, 0, 9, 0, 4, 0, 1, 1, 0, 4,
+ 0, 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24, 0, 27, 0, 30, 0, 32, 0, 35,
+ 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 48, 119, 0, 103, 0, 89, 0,
+ 77, 0, 67, 0, 57, 0, 48, 0, 40, 0, 33, 0, 26, 0, 20, 0, 14, 0, 9, 0,
+ 4, 0, 1, 1, 0, 4, 0, 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24, 0, 27,
+ 0, 30, 0, 32, 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 48,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 7, 0, 11, 0, 14,
+ 0, 17, 0, 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33, 0, 35, 0, 37, 0, 39,
+ 0, 41, 0, 43, 0, 45, 0, 119, 0, 105, 0, 92, 0, 80, 0, 70, 0, 60, 0, 52,
+ 0, 44, 0, 37, 0, 30, 0, 24, 0, 18, 0, 13, 0, 8, 0, 4, 0, 2, 0, 3,
+ 0, 7, 0, 11, 0, 14, 0, 17, 0, 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33,
+ 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0,
+ 105, 0, 92, 0, 80, 0, 70, 0, 60, 0, 52, 0, 44, 0, 37, 0, 30, 0, 24, 0,
+ 18, 0, 13, 0, 8, 0, 4, 0, 1, 1, 0, 3, 0, 7, 0, 11, 0, 14, 0, 17,
+ 0, 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33, 0, 35, 0, 37, 0, 39, 0, 41,
+ 0, 43, 0, 45, 119, 0, 105, 0, 92, 0, 80, 0, 70, 0, 60, 0, 52, 0, 44, 0,
+ 37, 0, 30, 0, 24, 0, 18, 0, 13, 0, 8, 0, 4, 0, 1, 1, 0, 3, 0, 7,
+ 0, 11, 0, 14, 0, 17, 0, 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33, 0, 35,
+ 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0, 24,
+ 0, 27, 0, 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39, 0, 41, 0, 120, 0, 106,
+ 0, 93, 0, 82, 0, 72, 0, 63, 0, 55, 0, 47, 0, 40, 0, 34, 0, 28, 0, 22,
+ 0, 17, 0, 12, 0, 8, 0, 3, 0, 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16,
+ 0, 19, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39,
+ 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 106, 0, 93, 0, 82, 0, 72, 0, 63, 0,
+ 55, 0, 47, 0, 40, 0, 34, 0, 28, 0, 22, 0, 17, 0, 12, 0, 8, 0, 3, 0,
+ 0, 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0, 24, 0, 27,
+ 0, 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39, 0, 41, 120, 0, 106, 0, 93, 0,
+ 82, 0, 72, 0, 63, 0, 55, 0, 47, 0, 40, 0, 34, 0, 28, 0, 22, 0, 17, 0,
+ 12, 0, 8, 0, 3, 0, 0, 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19,
+ 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39, 0, 41,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 6,
+ 0, 10, 0, 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 32,
+ 0, 34, 0, 36, 0, 38, 0, 120, 0, 107, 0, 95, 0, 85, 0, 75, 0, 66, 0, 58,
+ 0, 51, 0, 44, 0, 37, 0, 31, 0, 26, 0, 21, 0, 16, 0, 11, 0, 7, 0, 3,
+ 0, 0, 0, 3, 0, 6, 0, 10, 0, 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26,
+ 0, 28, 0, 30, 0, 32, 0, 34, 0, 36, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0,
+ 107, 0, 95, 0, 85, 0, 75, 0, 66, 0, 58, 0, 51, 0, 44, 0, 37, 0, 31, 0,
+ 26, 0, 21, 0, 16, 0, 11, 0, 7, 0, 3, 0, 0, 0, 0, 3, 0, 6, 0, 10,
+ 0, 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 32, 0, 34,
+ 0, 36, 0, 38, 120, 0, 107, 0, 95, 0, 85, 0, 75, 0, 66, 0, 58, 0, 51, 0,
+ 44, 0, 37, 0, 31, 0, 26, 0, 21, 0, 16, 0, 11, 0, 7, 0, 3, 0, 0, 0,
+ 0, 3, 0, 6, 0, 10, 0, 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26, 0, 28,
+ 0, 30, 0, 32, 0, 34, 0, 36, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 17,
+ 0, 20, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35, 0, 120, 0, 108,
+ 0, 97, 0, 86, 0, 77, 0, 69, 0, 61, 0, 53, 0, 47, 0, 40, 0, 35, 0, 29,
+ 0, 24, 0, 19, 0, 15, 0, 11, 0, 7, 0, 3, 0, 0, 0, 3, 0, 6, 0, 9,
+ 0, 12, 0, 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33,
+ 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 108, 0, 97, 0, 86, 0, 77, 0, 69, 0,
+ 61, 0, 53, 0, 47, 0, 40, 0, 35, 0, 29, 0, 24, 0, 19, 0, 15, 0, 11, 0,
+ 7, 0, 3, 0, 0, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 17, 0, 20,
+ 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35, 120, 0, 108, 0, 97, 0,
+ 86, 0, 77, 0, 69, 0, 61, 0, 53, 0, 47, 0, 40, 0, 35, 0, 29, 0, 24, 0,
+ 19, 0, 15, 0, 11, 0, 7, 0, 3, 0, 0, 0, 0, 3, 0, 6, 0, 9, 0, 12,
+ 0, 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19, 0, 21, 0, 23, 0, 26,
+ 0, 28, 0, 30, 0, 31, 0, 121, 0, 109, 0, 98, 0, 88, 0, 79, 0, 71, 0, 63,
+ 0, 56, 0, 50, 0, 43, 0, 38, 0, 32, 0, 27, 0, 23, 0, 18, 0, 14, 0, 10,
+ 0, 6, 0, 3, 0, 0, 0, 3, 0, 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19,
+ 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 109, 0, 98, 0, 88, 0, 79, 0, 71, 0, 63, 0, 56, 0, 50, 0, 43, 0, 38, 0,
+ 32, 0, 27, 0, 23, 0, 18, 0, 14, 0, 10, 0, 6, 0, 3, 0, 0, 0, 0, 3,
+ 0, 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19, 0, 21, 0, 23, 0, 26, 0, 28,
+ 0, 30, 0, 31, 121, 0, 109, 0, 98, 0, 88, 0, 79, 0, 71, 0, 63, 0, 56, 0,
+ 50, 0, 43, 0, 38, 0, 32, 0, 27, 0, 23, 0, 18, 0, 14, 0, 10, 0, 6, 0,
+ 3, 0, 0, 0, 0, 3, 0, 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19, 0, 21,
+ 0, 23, 0, 26, 0, 28, 0, 30, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 8, 0, 11,
+ 0, 13, 0, 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26, 0, 28, 0, 121, 0, 110,
+ 0, 99, 0, 90, 0, 81, 0, 73, 0, 66, 0, 59, 0, 52, 0, 46, 0, 41, 0, 35,
+ 0, 30, 0, 26, 0, 21, 0, 17, 0, 13, 0, 10, 0, 6, 0, 3, 0, 0, 0, 3,
+ 0, 5, 0, 8, 0, 11, 0, 13, 0, 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26,
+ 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 110, 0, 99, 0, 90, 0, 81, 0, 73, 0,
+ 66, 0, 59, 0, 52, 0, 46, 0, 41, 0, 35, 0, 30, 0, 26, 0, 21, 0, 17, 0,
+ 13, 0, 10, 0, 6, 0, 3, 0, 0, 0, 0, 3, 0, 5, 0, 8, 0, 11, 0, 13,
+ 0, 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26, 0, 28, 121, 0, 110, 0, 99, 0,
+ 90, 0, 81, 0, 73, 0, 66, 0, 59, 0, 52, 0, 46, 0, 41, 0, 35, 0, 30, 0,
+ 26, 0, 21, 0, 17, 0, 13, 0, 10, 0, 6, 0, 3, 0, 0, 0, 0, 3, 0, 5,
+ 0, 8, 0, 11, 0, 13, 0, 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26, 0, 28,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13, 0, 15, 0, 17, 0, 20,
+ 0, 22, 0, 24, 0, 25, 0, 121, 0, 110, 0, 100, 0, 91, 0, 83, 0, 75, 0, 68,
+ 0, 61, 0, 55, 0, 49, 0, 43, 0, 38, 0, 33, 0, 29, 0, 24, 0, 20, 0, 16,
+ 0, 13, 0, 9, 0, 6, 0, 3, 0, 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13,
+ 0, 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 110, 0, 100, 0, 91, 0, 83, 0, 75, 0, 68, 0, 61, 0, 55, 0, 49, 0, 43, 0,
+ 38, 0, 33, 0, 29, 0, 24, 0, 20, 0, 16, 0, 13, 0, 9, 0, 6, 0, 3, 0,
+ 0, 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13, 0, 15, 0, 17, 0, 20, 0, 22,
+ 0, 24, 0, 25, 121, 0, 110, 0, 100, 0, 91, 0, 83, 0, 75, 0, 68, 0, 61, 0,
+ 55, 0, 49, 0, 43, 0, 38, 0, 33, 0, 29, 0, 24, 0, 20, 0, 16, 0, 13, 0,
+ 9, 0, 6, 0, 3, 0, 0, 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13, 0, 15,
+ 0, 17, 0, 20, 0, 22, 0, 24, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 5,
+ 0, 7, 0, 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 0, 121, 0, 111,
+ 0, 102, 0, 93, 0, 85, 0, 77, 0, 70, 0, 63, 0, 57, 0, 51, 0, 46, 0, 41,
+ 0, 36, 0, 31, 0, 27, 0, 23, 0, 19, 0, 15, 0, 12, 0, 9, 0, 5, 0, 2,
+ 0, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21,
+ 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 111, 0, 102, 0, 93, 0, 85, 0, 77, 0,
+ 70, 0, 63, 0, 57, 0, 51, 0, 46, 0, 41, 0, 36, 0, 31, 0, 27, 0, 23, 0,
+ 19, 0, 15, 0, 12, 0, 9, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 5, 0, 7,
+ 0, 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 121, 0, 111, 0, 102, 0,
+ 93, 0, 85, 0, 77, 0, 70, 0, 63, 0, 57, 0, 51, 0, 46, 0, 41, 0, 36, 0,
+ 31, 0, 27, 0, 23, 0, 19, 0, 15, 0, 12, 0, 9, 0, 5, 0, 2, 0, 0, 0,
+ 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 14,
+ 0, 16, 0, 18, 0, 20, 0, 122, 0, 112, 0, 102, 0, 94, 0, 86, 0, 79, 0, 72,
+ 0, 65, 0, 59, 0, 54, 0, 48, 0, 43, 0, 38, 0, 34, 0, 30, 0, 26, 0, 22,
+ 0, 18, 0, 15, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 0, 2, 0, 5, 0, 7,
+ 0, 10, 0, 12, 0, 14, 0, 16, 0, 18, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 112, 0, 102, 0, 94, 0, 86, 0, 79, 0, 72, 0, 65, 0, 59, 0, 54, 0, 48, 0,
+ 43, 0, 38, 0, 34, 0, 30, 0, 26, 0, 22, 0, 18, 0, 15, 0, 11, 0, 8, 0,
+ 5, 0, 2, 0, 0, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 14, 0, 16,
+ 0, 18, 0, 20, 122, 0, 112, 0, 102, 0, 94, 0, 86, 0, 79, 0, 72, 0, 65, 0,
+ 59, 0, 54, 0, 48, 0, 43, 0, 38, 0, 34, 0, 30, 0, 26, 0, 22, 0, 18, 0,
+ 15, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 5, 0, 7, 0, 10,
+ 0, 12, 0, 14, 0, 16, 0, 18, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 0, 122, 0, 112,
+ 0, 103, 0, 95, 0, 87, 0, 80, 0, 74, 0, 67, 0, 61, 0, 56, 0, 51, 0, 46,
+ 0, 41, 0, 36, 0, 32, 0, 28, 0, 24, 0, 21, 0, 17, 0, 14, 0, 11, 0, 8,
+ 0, 5, 0, 2, 0, 0, 0, 2, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15,
+ 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 112, 0, 103, 0, 95, 0, 87, 0, 80, 0,
+ 74, 0, 67, 0, 61, 0, 56, 0, 51, 0, 46, 0, 41, 0, 36, 0, 32, 0, 28, 0,
+ 24, 0, 21, 0, 17, 0, 14, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 0, 0, 2,
+ 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 122, 0, 112, 0, 103, 0,
+ 95, 0, 87, 0, 80, 0, 74, 0, 67, 0, 61, 0, 56, 0, 51, 0, 46, 0, 41, 0,
+ 36, 0, 32, 0, 28, 0, 24, 0, 21, 0, 17, 0, 14, 0, 11, 0, 8, 0, 5, 0,
+ 2, 0, 0, 0, 0, 2, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 7, 0, 9,
+ 0, 11, 0, 13, 0, 15, 0, 122, 0, 113, 0, 104, 0, 96, 0, 89, 0, 82, 0, 75,
+ 0, 69, 0, 63, 0, 58, 0, 53, 0, 48, 0, 43, 0, 39, 0, 35, 0, 31, 0, 27,
+ 0, 23, 0, 20, 0, 17, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 0, 2,
+ 0, 4, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 113, 0, 104, 0, 96, 0, 89, 0, 82, 0, 75, 0, 69, 0, 63, 0, 58, 0, 53, 0,
+ 48, 0, 43, 0, 39, 0, 35, 0, 31, 0, 27, 0, 23, 0, 20, 0, 17, 0, 13, 0,
+ 10, 0, 7, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 7, 0, 9, 0, 11,
+ 0, 13, 0, 15, 122, 0, 113, 0, 104, 0, 96, 0, 89, 0, 82, 0, 75, 0, 69, 0,
+ 63, 0, 58, 0, 53, 0, 48, 0, 43, 0, 39, 0, 35, 0, 31, 0, 27, 0, 23, 0,
+ 20, 0, 17, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 4,
+ 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0, 122, 0, 113,
+ 0, 105, 0, 97, 0, 90, 0, 83, 0, 77, 0, 71, 0, 65, 0, 60, 0, 55, 0, 50,
+ 0, 45, 0, 41, 0, 37, 0, 33, 0, 29, 0, 26, 0, 22, 0, 19, 0, 16, 0, 13,
+ 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10,
+ 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 113, 0, 105, 0, 97, 0, 90, 0, 83, 0,
+ 77, 0, 71, 0, 65, 0, 60, 0, 55, 0, 50, 0, 45, 0, 41, 0, 37, 0, 33, 0,
+ 29, 0, 26, 0, 22, 0, 19, 0, 16, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0,
+ 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 122, 0, 113, 0, 105, 0,
+ 97, 0, 90, 0, 83, 0, 77, 0, 71, 0, 65, 0, 60, 0, 55, 0, 50, 0, 45, 0,
+ 41, 0, 37, 0, 33, 0, 29, 0, 26, 0, 22, 0, 19, 0, 16, 0, 13, 0, 10, 0,
+ 7, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4,
+ 0, 6, 0, 8, 0, 10, 0, 122, 0, 114, 0, 106, 0, 98, 0, 91, 0, 85, 0, 78,
+ 0, 72, 0, 67, 0, 62, 0, 57, 0, 52, 0, 47, 0, 43, 0, 39, 0, 35, 0, 31,
+ 0, 28, 0, 24, 0, 21, 0, 18, 0, 15, 0, 12, 0, 10, 0, 7, 0, 4, 0, 2,
+ 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 114, 0, 106, 0, 98, 0, 91, 0, 85, 0, 78, 0, 72, 0, 67, 0, 62, 0, 57, 0,
+ 52, 0, 47, 0, 43, 0, 39, 0, 35, 0, 31, 0, 28, 0, 24, 0, 21, 0, 18, 0,
+ 15, 0, 12, 0, 10, 0, 7, 0, 4, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 6,
+ 0, 8, 0, 10, 122, 0, 114, 0, 106, 0, 98, 0, 91, 0, 85, 0, 78, 0, 72, 0,
+ 67, 0, 62, 0, 57, 0, 52, 0, 47, 0, 43, 0, 39, 0, 35, 0, 31, 0, 28, 0,
+ 24, 0, 21, 0, 18, 0, 15, 0, 12, 0, 10, 0, 7, 0, 4, 0, 2, 0, 0, 0,
+ 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 123, 0, 114,
+ 0, 106, 0, 99, 0, 92, 0, 86, 0, 80, 0, 74, 0, 68, 0, 63, 0, 58, 0, 54,
+ 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 30, 0, 27, 0, 23, 0, 20, 0, 17,
+ 0, 15, 0, 12, 0, 9, 0, 7, 0, 4, 0, 2, 0, 0, 0, 2, 0, 4, 0, 6,
+ 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 114, 0, 106, 0, 99, 0, 92, 0, 86, 0,
+ 80, 0, 74, 0, 68, 0, 63, 0, 58, 0, 54, 0, 49, 0, 45, 0, 41, 0, 37, 0,
+ 34, 0, 30, 0, 27, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 9, 0, 7, 0,
+ 4, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 123, 0, 114, 0, 106, 0,
+ 99, 0, 92, 0, 86, 0, 80, 0, 74, 0, 68, 0, 63, 0, 58, 0, 54, 0, 49, 0,
+ 45, 0, 41, 0, 37, 0, 34, 0, 30, 0, 27, 0, 23, 0, 20, 0, 17, 0, 15, 0,
+ 12, 0, 9, 0, 7, 0, 4, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 4, 0, 6, 0, 123, 0, 115, 0, 107, 0, 100, 0, 93, 0, 87, 0, 81,
+ 0, 75, 0, 70, 0, 65, 0, 60, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36,
+ 0, 32, 0, 29, 0, 26, 0, 22, 0, 20, 0, 17, 0, 14, 0, 11, 0, 9, 0, 6,
+ 0, 4, 0, 2, 0, 0, 0, 2, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 115, 0, 107, 0, 100, 0, 93, 0, 87, 0, 81, 0, 75, 0, 70, 0, 65, 0, 60, 0,
+ 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 32, 0, 29, 0, 26, 0, 22, 0,
+ 20, 0, 17, 0, 14, 0, 11, 0, 9, 0, 6, 0, 4, 0, 2, 0, 0, 0, 0, 2,
+ 0, 4, 0, 6, 123, 0, 115, 0, 107, 0, 100, 0, 93, 0, 87, 0, 81, 0, 75, 0,
+ 70, 0, 65, 0, 60, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 32, 0,
+ 29, 0, 26, 0, 22, 0, 20, 0, 17, 0, 14, 0, 11, 0, 9, 0, 6, 0, 4, 0,
+ 2, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 123, 0, 115,
+ 0, 108, 0, 101, 0, 94, 0, 88, 0, 82, 0, 77, 0, 71, 0, 66, 0, 62, 0, 57,
+ 0, 53, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 31, 0, 28, 0, 25, 0, 22,
+ 0, 19, 0, 16, 0, 13, 0, 11, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 0, 2,
+ 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 108, 0, 101, 0, 94, 0, 88, 0,
+ 82, 0, 77, 0, 71, 0, 66, 0, 62, 0, 57, 0, 53, 0, 49, 0, 45, 0, 41, 0,
+ 37, 0, 34, 0, 31, 0, 28, 0, 25, 0, 22, 0, 19, 0, 16, 0, 13, 0, 11, 0,
+ 8, 0, 6, 0, 4, 0, 2, 0, 0, 0, 0, 2, 0, 4, 123, 0, 115, 0, 108, 0,
+ 101, 0, 94, 0, 88, 0, 82, 0, 77, 0, 71, 0, 66, 0, 62, 0, 57, 0, 53, 0,
+ 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 31, 0, 28, 0, 25, 0, 22, 0, 19, 0,
+ 16, 0, 13, 0, 11, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 0, 0, 2, 0, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 123, 0, 115, 0, 108, 0, 102, 0, 95, 0, 89, 0, 83,
+ 0, 78, 0, 73, 0, 68, 0, 63, 0, 59, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39,
+ 0, 36, 0, 33, 0, 30, 0, 26, 0, 24, 0, 21, 0, 18, 0, 15, 0, 13, 0, 10,
+ 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 115, 0, 108, 0, 102, 0, 95, 0, 89, 0, 83, 0, 78, 0, 73, 0, 68, 0, 63, 0,
+ 59, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 33, 0, 30, 0, 26, 0,
+ 24, 0, 21, 0, 18, 0, 15, 0, 13, 0, 10, 0, 8, 0, 6, 0, 4, 0, 2, 0,
+ 0, 0, 0, 1, 123, 0, 115, 0, 108, 0, 102, 0, 95, 0, 89, 0, 83, 0, 78, 0,
+ 73, 0, 68, 0, 63, 0, 59, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0,
+ 33, 0, 30, 0, 26, 0, 24, 0, 21, 0, 18, 0, 15, 0, 13, 0, 10, 0, 8, 0,
+ 6, 0, 4, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 116,
+ 0, 109, 0, 102, 0, 96, 0, 90, 0, 85, 0, 79, 0, 74, 0, 69, 0, 65, 0, 60,
+ 0, 56, 0, 52, 0, 48, 0, 45, 0, 41, 0, 38, 0, 35, 0, 31, 0, 28, 0, 25,
+ 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 10, 0, 8, 0, 6, 0, 4, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 116, 0, 109, 0, 102, 0, 96, 0, 90, 0,
+ 85, 0, 79, 0, 74, 0, 69, 0, 65, 0, 60, 0, 56, 0, 52, 0, 48, 0, 45, 0,
+ 41, 0, 38, 0, 35, 0, 31, 0, 28, 0, 25, 0, 23, 0, 20, 0, 17, 0, 15, 0,
+ 12, 0, 10, 0, 8, 0, 6, 0, 4, 0, 1, 0, 0, 0, 123, 0, 116, 0, 109, 0,
+ 102, 0, 96, 0, 90, 0, 85, 0, 79, 0, 74, 0, 69, 0, 65, 0, 60, 0, 56, 0,
+ 52, 0, 48, 0, 45, 0, 41, 0, 38, 0, 35, 0, 31, 0, 28, 0, 25, 0, 23, 0,
+ 20, 0, 17, 0, 15, 0, 12, 0, 10, 0, 8, 0, 6, 0, 4, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 63, 0, 85, 0, 95, 0, 102, 0,
+ 106, 0, 109, 0, 111, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0,
+ 119, 0,
+ 119, 0, 120, 0, 120, 0, 120, 0, 121, 0, 121, 0, 121, 0, 121, 0, 122, 0,
+ 122, 0,
+ 122, 0, 122, 0, 122, 0, 123, 0, 123, 0, 123, 0, 123, 0, 123, 0, 31, 31, 63,
+ 0,
+ 85, 0, 95, 0, 102, 0, 106, 0, 109, 0, 111, 0, 113, 0, 114, 0, 115, 0, 116,
+ 0,
+ 117, 0, 118, 0, 119, 0, 119, 0, 120, 0, 120, 0, 120, 0, 121, 0, 121, 0,
+ 121, 0,
+ 121, 0, 122, 0, 122, 0, 122, 0, 122, 0, 122, 0, 123, 0, 123, 0, 123, 0,
+ 123, 0,
+ 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 63, 0, 85, 0, 95, 0, 102, 0, 106, 0,
+ 109, 0, 111, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0, 119, 0,
+ 119, 0,
+ 120, 0, 120, 0, 120, 0, 121, 0, 121, 0, 121, 0, 121, 0, 122, 0, 122, 0,
+ 122, 0,
+ 122, 0, 122, 0, 123, 0, 123, 0, 123, 0, 123, 0, 123, 0, 31, 31, 63, 0, 85,
+ 0,
+ 95, 0, 102, 0, 106, 0, 109, 0, 111, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117,
+ 0,
+ 118, 0, 119, 0, 119, 0, 120, 0, 120, 0, 120, 0, 121, 0, 121, 0, 121, 0,
+ 121, 0,
+ 122, 0, 122, 0, 122, 0, 122, 0, 122, 0, 123, 0, 123, 0, 123, 0, 123, 0,
+ 123, 0,
+ 0, 0, 10, 0, 31, 0, 51, 0, 63, 0, 72, 0, 79, 0, 85, 0, 89, 0, 92, 0,
+ 95, 0, 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106, 0, 107, 0, 108, 0, 109,
+ 0,
+ 110, 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 0, 113, 0, 114, 0, 114, 0,
+ 115, 0,
+ 115, 0, 115, 0, 116, 0, 0, 63, 10, 10, 31, 0, 51, 0, 63, 0, 72, 0, 79, 0,
+ 85, 0, 89, 0, 92, 0, 95, 0, 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106, 0,
+ 107, 0, 108, 0, 109, 0, 110, 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 0,
+ 113, 0,
+ 114, 0, 114, 0, 115, 0, 115, 0, 115, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0,
+ 20, 0, 31, 0, 51, 0, 63, 0, 72, 0, 79, 0, 85, 0, 89, 0, 92, 0, 95, 0,
+ 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106, 0, 107, 0, 108, 0, 109, 0, 110,
+ 0,
+ 110, 0, 111, 0, 112, 0, 112, 0, 113, 0, 113, 0, 114, 0, 114, 0, 115, 0,
+ 115, 0,
+ 115, 0, 116, 0, 0, 63, 10, 10, 31, 0, 51, 0, 63, 0, 72, 0, 79, 0, 85, 0,
+ 89, 0, 92, 0, 95, 0, 98, 0, 100, 0, 102, 0, 103, 0, 105, 0, 106, 0, 107, 0,
+ 108, 0, 109, 0, 110, 0, 110, 0, 111, 0, 112, 0, 112, 0, 113, 0, 113, 0,
+ 114, 0,
+ 114, 0, 115, 0, 115, 0, 115, 0, 116, 0, 0, 0, 0, 0, 6, 0, 21, 0, 36, 0,
+ 47, 0, 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81, 0, 85, 0, 87, 0, 89, 0,
+ 92, 0, 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100, 0, 102, 0, 102, 0, 103, 0,
+ 104, 0, 105, 0, 106, 0, 106, 0, 107, 0, 108, 0, 108, 0, 109, 0, 0, 85, 0,
+ 31,
+ 6, 6, 21, 0, 36, 0, 47, 0, 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81, 0,
+ 85, 0, 87, 0, 89, 0, 92, 0, 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100, 0,
+ 102, 0, 102, 0, 103, 0, 104, 0, 105, 0, 106, 0, 106, 0, 107, 0, 108, 0,
+ 108, 0,
+ 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 85, 0, 31, 0, 12, 0, 21, 0, 36, 0, 47, 0,
+ 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81, 0, 85, 0, 87, 0, 89, 0, 92, 0,
+ 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100, 0, 102, 0, 102, 0, 103, 0, 104, 0,
+ 105, 0, 106, 0, 106, 0, 107, 0, 108, 0, 108, 0, 109, 0, 0, 85, 0, 31, 6, 6,
+ 21, 0, 36, 0, 47, 0, 56, 0, 63, 0, 69, 0, 74, 0, 78, 0, 81, 0, 85, 0,
+ 87, 0, 89, 0, 92, 0, 93, 0, 95, 0, 97, 0, 98, 0, 99, 0, 100, 0, 102, 0,
+ 102, 0, 103, 0, 104, 0, 105, 0, 106, 0, 106, 0, 107, 0, 108, 0, 108, 0,
+ 109, 0,
+ 0, 0, 0, 0, 0, 0, 4, 0, 15, 0, 28, 0, 38, 0, 46, 0, 53, 0, 58, 0,
+ 63, 0, 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82, 0, 85, 0, 86, 0, 88, 0,
+ 90, 0, 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 0, 100, 0,
+ 101, 0, 102, 0, 102, 0, 0, 95, 0, 51, 0, 21, 4, 4, 15, 0, 28, 0, 38, 0,
+ 46, 0, 53, 0, 58, 0, 63, 0, 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82, 0,
+ 85, 0, 86, 0, 88, 0, 90, 0, 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0,
+ 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0,
+ 51, 0, 21, 0, 8, 0, 15, 0, 28, 0, 38, 0, 46, 0, 53, 0, 58, 0, 63, 0,
+ 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82, 0, 85, 0, 86, 0, 88, 0, 90, 0,
+ 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0,
+ 102, 0, 102, 0, 0, 95, 0, 51, 0, 21, 4, 4, 15, 0, 28, 0, 38, 0, 46, 0,
+ 53, 0, 58, 0, 63, 0, 68, 0, 71, 0, 75, 0, 77, 0, 80, 0, 82, 0, 85, 0,
+ 86, 0, 88, 0, 90, 0, 91, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0,
+ 99, 0, 100, 0, 101, 0, 102, 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 12, 0, 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55, 0, 60, 0, 63, 0, 67, 0,
+ 70, 0, 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 0, 85, 0, 86, 0, 87, 0,
+ 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 0, 102, 0, 63,
+ 0, 36, 0, 15, 3, 3, 12, 0, 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55, 0,
+ 60, 0, 63, 0, 67, 0, 70, 0, 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 0,
+ 85, 0, 86, 0, 87, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0,
+ 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 102, 0, 63, 0, 36, 0, 15, 0, 6, 0, 12, 0,
+ 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55, 0, 60, 0, 63, 0, 67, 0, 70, 0,
+ 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 0, 85, 0, 86, 0, 87, 0, 89, 0,
+ 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 0, 102, 0, 63, 0, 36,
+ 0, 15, 3, 3, 12, 0, 23, 0, 31, 0, 39, 0, 45, 0, 51, 0, 55, 0, 60, 0,
+ 63, 0, 67, 0, 70, 0, 72, 0, 75, 0, 77, 0, 79, 0, 81, 0, 83, 0, 85, 0,
+ 86, 0, 87, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 10, 0, 19, 0, 27, 0, 34, 0,
+ 39, 0, 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63, 0, 66, 0, 69, 0, 71, 0,
+ 73, 0, 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83, 0, 85, 0, 86, 0, 87, 0,
+ 88, 0, 89, 0, 90, 0, 0, 106, 0, 72, 0, 47, 0, 28, 0, 12, 2, 2, 10, 0,
+ 19, 0, 27, 0, 34, 0, 39, 0, 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63, 0,
+ 66, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83, 0,
+ 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0,
+ 72, 0, 47, 0, 28, 0, 12, 0, 4, 0, 10, 0, 19, 0, 27, 0, 34, 0, 39, 0,
+ 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63, 0, 66, 0, 69, 0, 71, 0, 73, 0,
+ 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83, 0, 85, 0, 86, 0, 87, 0, 88, 0,
+ 89, 0, 90, 0, 0, 106, 0, 72, 0, 47, 0, 28, 0, 12, 2, 2, 10, 0, 19, 0,
+ 27, 0, 34, 0, 39, 0, 44, 0, 49, 0, 53, 0, 57, 0, 60, 0, 63, 0, 66, 0,
+ 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 0, 80, 0, 82, 0, 83, 0, 85, 0,
+ 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 9, 0, 17, 0, 23, 0, 30, 0, 35, 0, 40, 0, 44, 0, 48, 0,
+ 52, 0, 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68, 0, 70, 0, 72, 0, 74, 0,
+ 75, 0, 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83, 0, 85, 0, 0, 109, 0, 79,
+ 0, 56, 0, 38, 0, 23, 0, 10, 2, 2, 9, 0, 17, 0, 23, 0, 30, 0, 35, 0,
+ 40, 0, 44, 0, 48, 0, 52, 0, 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68, 0,
+ 70, 0, 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83, 0,
+ 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, 79, 0, 56, 0, 38, 0, 23, 0, 10, 0,
+ 4, 0, 9, 0, 17, 0, 23, 0, 30, 0, 35, 0, 40, 0, 44, 0, 48, 0, 52, 0,
+ 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68, 0, 70, 0, 72, 0, 74, 0, 75, 0,
+ 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83, 0, 85, 0, 0, 109, 0, 79, 0, 56,
+ 0, 38, 0, 23, 0, 10, 2, 2, 9, 0, 17, 0, 23, 0, 30, 0, 35, 0, 40, 0,
+ 44, 0, 48, 0, 52, 0, 55, 0, 58, 0, 61, 0, 63, 0, 66, 0, 68, 0, 70, 0,
+ 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 80, 0, 81, 0, 82, 0, 83, 0, 85, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 7, 0, 15, 0,
+ 21, 0, 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47, 0, 51, 0, 53, 0, 56, 0,
+ 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 72, 0, 74, 0, 75, 0,
+ 77, 0, 78, 0, 79, 0, 0, 111, 0, 85, 0, 63, 0, 46, 0, 31, 0, 19, 0, 9,
+ 2, 2, 7, 0, 15, 0, 21, 0, 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47, 0,
+ 51, 0, 53, 0, 56, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0,
+ 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0,
+ 85, 0, 63, 0, 46, 0, 31, 0, 19, 0, 9, 0, 4, 0, 7, 0, 15, 0, 21, 0,
+ 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47, 0, 51, 0, 53, 0, 56, 0, 59, 0,
+ 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 72, 0, 74, 0, 75, 0, 77, 0,
+ 78, 0, 79, 0, 0, 111, 0, 85, 0, 63, 0, 46, 0, 31, 0, 19, 0, 9, 2, 2,
+ 7, 0, 15, 0, 21, 0, 26, 0, 31, 0, 36, 0, 40, 0, 44, 0, 47, 0, 51, 0,
+ 53, 0, 56, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 72, 0,
+ 74, 0, 75, 0, 77, 0, 78, 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 13, 0, 19, 0, 24, 0, 28, 0, 33, 0,
+ 37, 0, 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55, 0, 57, 0, 59, 0, 61, 0,
+ 63, 0, 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73, 0, 74, 0, 0, 113, 0, 89,
+ 0, 69, 0, 53, 0, 39, 0, 27, 0, 17, 0, 7, 1, 1, 7, 0, 13, 0, 19, 0,
+ 24, 0, 28, 0, 33, 0, 37, 0, 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55, 0,
+ 57, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73, 0,
+ 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, 89, 0, 69, 0, 53, 0, 39, 0, 27, 0,
+ 17, 0, 7, 0, 2, 0, 7, 0, 13, 0, 19, 0, 24, 0, 28, 0, 33, 0, 37, 0,
+ 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55, 0, 57, 0, 59, 0, 61, 0, 63, 0,
+ 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73, 0, 74, 0, 0, 113, 0, 89, 0, 69,
+ 0, 53, 0, 39, 0, 27, 0, 17, 0, 7, 1, 1, 7, 0, 13, 0, 19, 0, 24, 0,
+ 28, 0, 33, 0, 37, 0, 40, 0, 44, 0, 47, 0, 50, 0, 52, 0, 55, 0, 57, 0,
+ 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 68, 0, 70, 0, 71, 0, 73, 0, 74, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 6, 0, 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34, 0, 37, 0, 40, 0, 43, 0,
+ 46, 0, 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0,
+ 66, 0, 68, 0, 69, 0, 0, 114, 0, 92, 0, 74, 0, 58, 0, 45, 0, 34, 0, 23,
+ 0, 15, 0, 7, 1, 1, 6, 0, 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34, 0,
+ 37, 0, 40, 0, 43, 0, 46, 0, 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60, 0,
+ 62, 0, 63, 0, 65, 0, 66, 0, 68, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 0,
+ 92, 0, 74, 0, 58, 0, 45, 0, 34, 0, 23, 0, 15, 0, 7, 0, 2, 0, 6, 0,
+ 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34, 0, 37, 0, 40, 0, 43, 0, 46, 0,
+ 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0, 66, 0,
+ 68, 0, 69, 0, 0, 114, 0, 92, 0, 74, 0, 58, 0, 45, 0, 34, 0, 23, 0, 15,
+ 0, 7, 1, 1, 6, 0, 12, 0, 17, 0, 22, 0, 26, 0, 30, 0, 34, 0, 37, 0,
+ 40, 0, 43, 0, 46, 0, 49, 0, 51, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62, 0,
+ 63, 0, 65, 0, 66, 0, 68, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 11, 0, 15, 0, 20, 0,
+ 24, 0, 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 51, 0,
+ 53, 0, 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0, 0, 115, 0, 95,
+ 0, 78, 0, 63, 0, 51, 0, 39, 0, 30, 0, 21, 0, 13, 0, 6, 1, 1, 5, 0,
+ 11, 0, 15, 0, 20, 0, 24, 0, 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43, 0,
+ 46, 0, 48, 0, 51, 0, 53, 0, 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63, 0,
+ 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 95, 0, 78, 0, 63, 0, 51, 0, 39, 0,
+ 30, 0, 21, 0, 13, 0, 6, 0, 2, 0, 5, 0, 11, 0, 15, 0, 20, 0, 24, 0,
+ 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 51, 0, 53, 0,
+ 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0, 0, 115, 0, 95, 0, 78,
+ 0, 63, 0, 51, 0, 39, 0, 30, 0, 21, 0, 13, 0, 6, 1, 1, 5, 0, 11, 0,
+ 15, 0, 20, 0, 24, 0, 28, 0, 31, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0,
+ 48, 0, 51, 0, 53, 0, 55, 0, 57, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 5, 0, 10, 0, 14, 0, 18, 0, 22, 0, 26, 0, 29, 0, 32, 0,
+ 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50, 0, 52, 0, 54, 0, 55, 0,
+ 57, 0, 59, 0, 60, 0, 0, 116, 0, 98, 0, 81, 0, 68, 0, 55, 0, 44, 0, 35,
+ 0, 26, 0, 19, 0, 12, 0, 5, 1, 1, 5, 0, 10, 0, 14, 0, 18, 0, 22, 0,
+ 26, 0, 29, 0, 32, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50, 0,
+ 52, 0, 54, 0, 55, 0, 57, 0, 59, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0,
+ 98, 0, 81, 0, 68, 0, 55, 0, 44, 0, 35, 0, 26, 0, 19, 0, 12, 0, 5, 0,
+ 2, 0, 5, 0, 10, 0, 14, 0, 18, 0, 22, 0, 26, 0, 29, 0, 32, 0, 35, 0,
+ 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50, 0, 52, 0, 54, 0, 55, 0, 57, 0,
+ 59, 0, 60, 0, 0, 116, 0, 98, 0, 81, 0, 68, 0, 55, 0, 44, 0, 35, 0, 26,
+ 0, 19, 0, 12, 0, 5, 1, 1, 5, 0, 10, 0, 14, 0, 18, 0, 22, 0, 26, 0,
+ 29, 0, 32, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 50, 0, 52, 0,
+ 54, 0, 55, 0, 57, 0, 59, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 9, 0,
+ 13, 0, 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33, 0, 36, 0, 38, 0, 41, 0,
+ 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 56, 0, 0, 117, 0, 100,
+ 0, 85, 0, 71, 0, 60, 0, 49, 0, 40, 0, 31, 0, 24, 0, 17, 0, 11, 0, 5,
+ 1, 1, 4, 0, 9, 0, 13, 0, 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33, 0,
+ 36, 0, 38, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 100, 0, 85, 0, 71, 0, 60, 0, 49, 0,
+ 40, 0, 31, 0, 24, 0, 17, 0, 11, 0, 5, 0, 2, 0, 4, 0, 9, 0, 13, 0,
+ 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33, 0, 36, 0, 38, 0, 41, 0, 43, 0,
+ 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 56, 0, 0, 117, 0, 100, 0, 85,
+ 0, 71, 0, 60, 0, 49, 0, 40, 0, 31, 0, 24, 0, 17, 0, 11, 0, 5, 1, 1,
+ 4, 0, 9, 0, 13, 0, 17, 0, 21, 0, 24, 0, 27, 0, 30, 0, 33, 0, 36, 0,
+ 38, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 8, 0, 12, 0, 16, 0, 19, 0, 23, 0,
+ 26, 0, 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0,
+ 49, 0, 51, 0, 52, 0, 0, 118, 0, 102, 0, 87, 0, 75, 0, 63, 0, 53, 0, 44,
+ 0, 36, 0, 28, 0, 22, 0, 15, 0, 10, 0, 4, 1, 1, 4, 0, 8, 0, 12, 0,
+ 16, 0, 19, 0, 23, 0, 26, 0, 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41, 0,
+ 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 0,
+ 102, 0, 87, 0, 75, 0, 63, 0, 53, 0, 44, 0, 36, 0, 28, 0, 22, 0, 15, 0,
+ 10, 0, 4, 0, 2, 0, 4, 0, 8, 0, 12, 0, 16, 0, 19, 0, 23, 0, 26, 0,
+ 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0,
+ 51, 0, 52, 0, 0, 118, 0, 102, 0, 87, 0, 75, 0, 63, 0, 53, 0, 44, 0, 36,
+ 0, 28, 0, 22, 0, 15, 0, 10, 0, 4, 1, 1, 4, 0, 8, 0, 12, 0, 16, 0,
+ 19, 0, 23, 0, 26, 0, 29, 0, 31, 0, 34, 0, 36, 0, 39, 0, 41, 0, 43, 0,
+ 45, 0, 47, 0, 49, 0, 51, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 4, 0, 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24, 0, 27, 0, 30, 0, 32, 0,
+ 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 48, 0, 0, 119, 0, 103,
+ 0, 89, 0, 77, 0, 67, 0, 57, 0, 48, 0, 40, 0, 33, 0, 26, 0, 20, 0, 14,
+ 0, 9, 0, 4, 1, 1, 4, 0, 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24, 0,
+ 27, 0, 30, 0, 32, 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0,
+ 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 103, 0, 89, 0, 77, 0, 67, 0, 57, 0,
+ 48, 0, 40, 0, 33, 0, 26, 0, 20, 0, 14, 0, 9, 0, 4, 0, 2, 0, 4, 0,
+ 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24, 0, 27, 0, 30, 0, 32, 0, 35, 0,
+ 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 48, 0, 0, 119, 0, 103, 0, 89,
+ 0, 77, 0, 67, 0, 57, 0, 48, 0, 40, 0, 33, 0, 26, 0, 20, 0, 14, 0, 9,
+ 0, 4, 1, 1, 4, 0, 8, 0, 11, 0, 15, 0, 18, 0, 21, 0, 24, 0, 27, 0,
+ 30, 0, 32, 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 48, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 7, 0, 11, 0, 14, 0,
+ 17, 0, 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33, 0, 35, 0, 37, 0, 39, 0,
+ 41, 0, 43, 0, 45, 0, 0, 119, 0, 105, 0, 92, 0, 80, 0, 70, 0, 60, 0, 52,
+ 0, 44, 0, 37, 0, 30, 0, 24, 0, 18, 0, 13, 0, 8, 0, 4, 1, 1, 3, 0,
+ 7, 0, 11, 0, 14, 0, 17, 0, 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33, 0,
+ 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0,
+ 105, 0, 92, 0, 80, 0, 70, 0, 60, 0, 52, 0, 44, 0, 37, 0, 30, 0, 24, 0,
+ 18, 0, 13, 0, 8, 0, 4, 0, 2, 0, 3, 0, 7, 0, 11, 0, 14, 0, 17, 0,
+ 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33, 0, 35, 0, 37, 0, 39, 0, 41, 0,
+ 43, 0, 45, 0, 0, 119, 0, 105, 0, 92, 0, 80, 0, 70, 0, 60, 0, 52, 0, 44,
+ 0, 37, 0, 30, 0, 24, 0, 18, 0, 13, 0, 8, 0, 4, 1, 1, 3, 0, 7, 0,
+ 11, 0, 14, 0, 17, 0, 20, 0, 23, 0, 26, 0, 28, 0, 31, 0, 33, 0, 35, 0,
+ 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0, 24, 0,
+ 27, 0, 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39, 0, 41, 0, 0, 120, 0, 106,
+ 0, 93, 0, 82, 0, 72, 0, 63, 0, 55, 0, 47, 0, 40, 0, 34, 0, 28, 0, 22,
+ 0, 17, 0, 12, 0, 8, 0, 3, 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16, 0,
+ 19, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39, 0,
+ 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 106, 0, 93, 0, 82, 0, 72, 0, 63, 0,
+ 55, 0, 47, 0, 40, 0, 34, 0, 28, 0, 22, 0, 17, 0, 12, 0, 8, 0, 3, 0,
+ 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0, 24, 0, 27, 0,
+ 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39, 0, 41, 0, 0, 120, 0, 106, 0, 93,
+ 0, 82, 0, 72, 0, 63, 0, 55, 0, 47, 0, 40, 0, 34, 0, 28, 0, 22, 0, 17,
+ 0, 12, 0, 8, 0, 3, 0, 0, 3, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0,
+ 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 34, 0, 36, 0, 37, 0, 39, 0, 41, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 6, 0,
+ 10, 0, 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 32, 0,
+ 34, 0, 36, 0, 38, 0, 0, 120, 0, 107, 0, 95, 0, 85, 0, 75, 0, 66, 0, 58,
+ 0, 51, 0, 44, 0, 37, 0, 31, 0, 26, 0, 21, 0, 16, 0, 11, 0, 7, 0, 3,
+ 0, 0, 3, 0, 6, 0, 10, 0, 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26, 0,
+ 28, 0, 30, 0, 32, 0, 34, 0, 36, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0,
+ 107, 0, 95, 0, 85, 0, 75, 0, 66, 0, 58, 0, 51, 0, 44, 0, 37, 0, 31, 0,
+ 26, 0, 21, 0, 16, 0, 11, 0, 7, 0, 3, 0, 0, 0, 3, 0, 6, 0, 10, 0,
+ 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 32, 0, 34, 0,
+ 36, 0, 38, 0, 0, 120, 0, 107, 0, 95, 0, 85, 0, 75, 0, 66, 0, 58, 0, 51,
+ 0, 44, 0, 37, 0, 31, 0, 26, 0, 21, 0, 16, 0, 11, 0, 7, 0, 3, 0, 0,
+ 3, 0, 6, 0, 10, 0, 13, 0, 15, 0, 18, 0, 21, 0, 23, 0, 26, 0, 28, 0,
+ 30, 0, 32, 0, 34, 0, 36, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 17, 0,
+ 20, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35, 0, 0, 120, 0, 108,
+ 0, 97, 0, 86, 0, 77, 0, 69, 0, 61, 0, 53, 0, 47, 0, 40, 0, 35, 0, 29,
+ 0, 24, 0, 19, 0, 15, 0, 11, 0, 7, 0, 3, 0, 0, 3, 0, 6, 0, 9, 0,
+ 12, 0, 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33, 0,
+ 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 108, 0, 97, 0, 86, 0, 77, 0, 69, 0,
+ 61, 0, 53, 0, 47, 0, 40, 0, 35, 0, 29, 0, 24, 0, 19, 0, 15, 0, 11, 0,
+ 7, 0, 3, 0, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 17, 0, 20, 0,
+ 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35, 0, 0, 120, 0, 108, 0, 97,
+ 0, 86, 0, 77, 0, 69, 0, 61, 0, 53, 0, 47, 0, 40, 0, 35, 0, 29, 0, 24,
+ 0, 19, 0, 15, 0, 11, 0, 7, 0, 3, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0,
+ 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19, 0, 21, 0, 23, 0, 26, 0,
+ 28, 0, 30, 0, 31, 0, 0, 121, 0, 109, 0, 98, 0, 88, 0, 79, 0, 71, 0, 63,
+ 0, 56, 0, 50, 0, 43, 0, 38, 0, 32, 0, 27, 0, 23, 0, 18, 0, 14, 0, 10,
+ 0, 6, 0, 3, 0, 0, 3, 0, 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19, 0,
+ 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 109, 0, 98, 0, 88, 0, 79, 0, 71, 0, 63, 0, 56, 0, 50, 0, 43, 0, 38, 0,
+ 32, 0, 27, 0, 23, 0, 18, 0, 14, 0, 10, 0, 6, 0, 3, 0, 0, 0, 3, 0,
+ 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19, 0, 21, 0, 23, 0, 26, 0, 28, 0,
+ 30, 0, 31, 0, 0, 121, 0, 109, 0, 98, 0, 88, 0, 79, 0, 71, 0, 63, 0, 56,
+ 0, 50, 0, 43, 0, 38, 0, 32, 0, 27, 0, 23, 0, 18, 0, 14, 0, 10, 0, 6,
+ 0, 3, 0, 0, 3, 0, 6, 0, 9, 0, 11, 0, 14, 0, 17, 0, 19, 0, 21, 0,
+ 23, 0, 26, 0, 28, 0, 30, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 8, 0, 11, 0,
+ 13, 0, 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26, 0, 28, 0, 0, 121, 0, 110,
+ 0, 99, 0, 90, 0, 81, 0, 73, 0, 66, 0, 59, 0, 52, 0, 46, 0, 41, 0, 35,
+ 0, 30, 0, 26, 0, 21, 0, 17, 0, 13, 0, 10, 0, 6, 0, 3, 0, 0, 3, 0,
+ 5, 0, 8, 0, 11, 0, 13, 0, 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26, 0,
+ 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 110, 0, 99, 0, 90, 0, 81, 0, 73, 0,
+ 66, 0, 59, 0, 52, 0, 46, 0, 41, 0, 35, 0, 30, 0, 26, 0, 21, 0, 17, 0,
+ 13, 0, 10, 0, 6, 0, 3, 0, 0, 0, 3, 0, 5, 0, 8, 0, 11, 0, 13, 0,
+ 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26, 0, 28, 0, 0, 121, 0, 110, 0, 99,
+ 0, 90, 0, 81, 0, 73, 0, 66, 0, 59, 0, 52, 0, 46, 0, 41, 0, 35, 0, 30,
+ 0, 26, 0, 21, 0, 17, 0, 13, 0, 10, 0, 6, 0, 3, 0, 0, 3, 0, 5, 0,
+ 8, 0, 11, 0, 13, 0, 16, 0, 18, 0, 20, 0, 22, 0, 25, 0, 26, 0, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13, 0, 15, 0, 17, 0, 20, 0,
+ 22, 0, 24, 0, 25, 0, 0, 121, 0, 110, 0, 100, 0, 91, 0, 83, 0, 75, 0, 68,
+ 0, 61, 0, 55, 0, 49, 0, 43, 0, 38, 0, 33, 0, 29, 0, 24, 0, 20, 0, 16,
+ 0, 13, 0, 9, 0, 6, 0, 3, 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13, 0,
+ 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 110, 0, 100, 0, 91, 0, 83, 0, 75, 0, 68, 0, 61, 0, 55, 0, 49, 0, 43, 0,
+ 38, 0, 33, 0, 29, 0, 24, 0, 20, 0, 16, 0, 13, 0, 9, 0, 6, 0, 3, 0,
+ 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13, 0, 15, 0, 17, 0, 20, 0, 22, 0,
+ 24, 0, 25, 0, 0, 121, 0, 110, 0, 100, 0, 91, 0, 83, 0, 75, 0, 68, 0, 61,
+ 0, 55, 0, 49, 0, 43, 0, 38, 0, 33, 0, 29, 0, 24, 0, 20, 0, 16, 0, 13,
+ 0, 9, 0, 6, 0, 3, 0, 0, 2, 0, 5, 0, 8, 0, 10, 0, 13, 0, 15, 0,
+ 17, 0, 20, 0, 22, 0, 24, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 5, 0,
+ 7, 0, 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 0, 0, 121, 0, 111,
+ 0, 102, 0, 93, 0, 85, 0, 77, 0, 70, 0, 63, 0, 57, 0, 51, 0, 46, 0, 41,
+ 0, 36, 0, 31, 0, 27, 0, 23, 0, 19, 0, 15, 0, 12, 0, 9, 0, 5, 0, 2,
+ 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21, 0,
+ 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 111, 0, 102, 0, 93, 0, 85, 0, 77, 0,
+ 70, 0, 63, 0, 57, 0, 51, 0, 46, 0, 41, 0, 36, 0, 31, 0, 27, 0, 23, 0,
+ 19, 0, 15, 0, 12, 0, 9, 0, 5, 0, 2, 0, 0, 0, 2, 0, 5, 0, 7, 0,
+ 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 0, 0, 121, 0, 111, 0, 102,
+ 0, 93, 0, 85, 0, 77, 0, 70, 0, 63, 0, 57, 0, 51, 0, 46, 0, 41, 0, 36,
+ 0, 31, 0, 27, 0, 23, 0, 19, 0, 15, 0, 12, 0, 9, 0, 5, 0, 2, 0, 0,
+ 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 14, 0,
+ 16, 0, 18, 0, 20, 0, 0, 122, 0, 112, 0, 102, 0, 94, 0, 86, 0, 79, 0, 72,
+ 0, 65, 0, 59, 0, 54, 0, 48, 0, 43, 0, 38, 0, 34, 0, 30, 0, 26, 0, 22,
+ 0, 18, 0, 15, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 2, 0, 5, 0, 7, 0,
+ 10, 0, 12, 0, 14, 0, 16, 0, 18, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 112, 0, 102, 0, 94, 0, 86, 0, 79, 0, 72, 0, 65, 0, 59, 0, 54, 0, 48, 0,
+ 43, 0, 38, 0, 34, 0, 30, 0, 26, 0, 22, 0, 18, 0, 15, 0, 11, 0, 8, 0,
+ 5, 0, 2, 0, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 14, 0, 16, 0,
+ 18, 0, 20, 0, 0, 122, 0, 112, 0, 102, 0, 94, 0, 86, 0, 79, 0, 72, 0, 65,
+ 0, 59, 0, 54, 0, 48, 0, 43, 0, 38, 0, 34, 0, 30, 0, 26, 0, 22, 0, 18,
+ 0, 15, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0,
+ 12, 0, 14, 0, 16, 0, 18, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 0, 0, 122, 0, 112,
+ 0, 103, 0, 95, 0, 87, 0, 80, 0, 74, 0, 67, 0, 61, 0, 56, 0, 51, 0, 46,
+ 0, 41, 0, 36, 0, 32, 0, 28, 0, 24, 0, 21, 0, 17, 0, 14, 0, 11, 0, 8,
+ 0, 5, 0, 2, 0, 0, 2, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0,
+ 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 112, 0, 103, 0, 95, 0, 87, 0, 80, 0,
+ 74, 0, 67, 0, 61, 0, 56, 0, 51, 0, 46, 0, 41, 0, 36, 0, 32, 0, 28, 0,
+ 24, 0, 21, 0, 17, 0, 14, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 0, 2, 0,
+ 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 0, 0, 122, 0, 112, 0, 103,
+ 0, 95, 0, 87, 0, 80, 0, 74, 0, 67, 0, 61, 0, 56, 0, 51, 0, 46, 0, 41,
+ 0, 36, 0, 32, 0, 28, 0, 24, 0, 21, 0, 17, 0, 14, 0, 11, 0, 8, 0, 5,
+ 0, 2, 0, 0, 2, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 7, 0, 9, 0,
+ 11, 0, 13, 0, 15, 0, 0, 122, 0, 113, 0, 104, 0, 96, 0, 89, 0, 82, 0, 75,
+ 0, 69, 0, 63, 0, 58, 0, 53, 0, 48, 0, 43, 0, 39, 0, 35, 0, 31, 0, 27,
+ 0, 23, 0, 20, 0, 17, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 2, 0,
+ 4, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 113, 0, 104, 0, 96, 0, 89, 0, 82, 0, 75, 0, 69, 0, 63, 0, 58, 0, 53, 0,
+ 48, 0, 43, 0, 39, 0, 35, 0, 31, 0, 27, 0, 23, 0, 20, 0, 17, 0, 13, 0,
+ 10, 0, 7, 0, 5, 0, 2, 0, 0, 0, 2, 0, 4, 0, 7, 0, 9, 0, 11, 0,
+ 13, 0, 15, 0, 0, 122, 0, 113, 0, 104, 0, 96, 0, 89, 0, 82, 0, 75, 0, 69,
+ 0, 63, 0, 58, 0, 53, 0, 48, 0, 43, 0, 39, 0, 35, 0, 31, 0, 27, 0, 23,
+ 0, 20, 0, 17, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 2, 0, 4, 0,
+ 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0, 0, 122, 0, 113,
+ 0, 105, 0, 97, 0, 90, 0, 83, 0, 77, 0, 71, 0, 65, 0, 60, 0, 55, 0, 50,
+ 0, 45, 0, 41, 0, 37, 0, 33, 0, 29, 0, 26, 0, 22, 0, 19, 0, 16, 0, 13,
+ 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0,
+ 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 113, 0, 105, 0, 97, 0, 90, 0, 83, 0,
+ 77, 0, 71, 0, 65, 0, 60, 0, 55, 0, 50, 0, 45, 0, 41, 0, 37, 0, 33, 0,
+ 29, 0, 26, 0, 22, 0, 19, 0, 16, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0,
+ 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0, 0, 122, 0, 113, 0, 105,
+ 0, 97, 0, 90, 0, 83, 0, 77, 0, 71, 0, 65, 0, 60, 0, 55, 0, 50, 0, 45,
+ 0, 41, 0, 37, 0, 33, 0, 29, 0, 26, 0, 22, 0, 19, 0, 16, 0, 13, 0, 10,
+ 0, 7, 0, 5, 0, 2, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0,
+ 6, 0, 8, 0, 10, 0, 0, 122, 0, 114, 0, 106, 0, 98, 0, 91, 0, 85, 0, 78,
+ 0, 72, 0, 67, 0, 62, 0, 57, 0, 52, 0, 47, 0, 43, 0, 39, 0, 35, 0, 31,
+ 0, 28, 0, 24, 0, 21, 0, 18, 0, 15, 0, 12, 0, 10, 0, 7, 0, 4, 0, 2,
+ 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 114, 0, 106, 0, 98, 0, 91, 0, 85, 0, 78, 0, 72, 0, 67, 0, 62, 0, 57, 0,
+ 52, 0, 47, 0, 43, 0, 39, 0, 35, 0, 31, 0, 28, 0, 24, 0, 21, 0, 18, 0,
+ 15, 0, 12, 0, 10, 0, 7, 0, 4, 0, 2, 0, 0, 0, 2, 0, 4, 0, 6, 0,
+ 8, 0, 10, 0, 0, 122, 0, 114, 0, 106, 0, 98, 0, 91, 0, 85, 0, 78, 0, 72,
+ 0, 67, 0, 62, 0, 57, 0, 52, 0, 47, 0, 43, 0, 39, 0, 35, 0, 31, 0, 28,
+ 0, 24, 0, 21, 0, 18, 0, 15, 0, 12, 0, 10, 0, 7, 0, 4, 0, 2, 0, 0,
+ 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 0, 123, 0, 114,
+ 0, 106, 0, 99, 0, 92, 0, 86, 0, 80, 0, 74, 0, 68, 0, 63, 0, 58, 0, 54,
+ 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 30, 0, 27, 0, 23, 0, 20, 0, 17,
+ 0, 15, 0, 12, 0, 9, 0, 7, 0, 4, 0, 2, 0, 0, 2, 0, 4, 0, 6, 0,
+ 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 114, 0, 106, 0, 99, 0, 92, 0, 86, 0,
+ 80, 0, 74, 0, 68, 0, 63, 0, 58, 0, 54, 0, 49, 0, 45, 0, 41, 0, 37, 0,
+ 34, 0, 30, 0, 27, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 9, 0, 7, 0,
+ 4, 0, 2, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 0, 123, 0, 114, 0, 106,
+ 0, 99, 0, 92, 0, 86, 0, 80, 0, 74, 0, 68, 0, 63, 0, 58, 0, 54, 0, 49,
+ 0, 45, 0, 41, 0, 37, 0, 34, 0, 30, 0, 27, 0, 23, 0, 20, 0, 17, 0, 15,
+ 0, 12, 0, 9, 0, 7, 0, 4, 0, 2, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 4, 0, 6, 0, 0, 123, 0, 115, 0, 107, 0, 100, 0, 93, 0, 87, 0, 81,
+ 0, 75, 0, 70, 0, 65, 0, 60, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36,
+ 0, 32, 0, 29, 0, 26, 0, 22, 0, 20, 0, 17, 0, 14, 0, 11, 0, 9, 0, 6,
+ 0, 4, 0, 2, 0, 0, 2, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 115, 0, 107, 0, 100, 0, 93, 0, 87, 0, 81, 0, 75, 0, 70, 0, 65, 0, 60, 0,
+ 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 32, 0, 29, 0, 26, 0, 22, 0,
+ 20, 0, 17, 0, 14, 0, 11, 0, 9, 0, 6, 0, 4, 0, 2, 0, 0, 0, 2, 0,
+ 4, 0, 6, 0, 0, 123, 0, 115, 0, 107, 0, 100, 0, 93, 0, 87, 0, 81, 0, 75,
+ 0, 70, 0, 65, 0, 60, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 32,
+ 0, 29, 0, 26, 0, 22, 0, 20, 0, 17, 0, 14, 0, 11, 0, 9, 0, 6, 0, 4,
+ 0, 2, 0, 0, 2, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 123, 0, 115,
+ 0, 108, 0, 101, 0, 94, 0, 88, 0, 82, 0, 77, 0, 71, 0, 66, 0, 62, 0, 57,
+ 0, 53, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 31, 0, 28, 0, 25, 0, 22,
+ 0, 19, 0, 16, 0, 13, 0, 11, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 2, 0,
+ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 108, 0, 101, 0, 94, 0, 88, 0,
+ 82, 0, 77, 0, 71, 0, 66, 0, 62, 0, 57, 0, 53, 0, 49, 0, 45, 0, 41, 0,
+ 37, 0, 34, 0, 31, 0, 28, 0, 25, 0, 22, 0, 19, 0, 16, 0, 13, 0, 11, 0,
+ 8, 0, 6, 0, 4, 0, 2, 0, 0, 0, 2, 0, 4, 0, 0, 123, 0, 115, 0, 108,
+ 0, 101, 0, 94, 0, 88, 0, 82, 0, 77, 0, 71, 0, 66, 0, 62, 0, 57, 0, 53,
+ 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 31, 0, 28, 0, 25, 0, 22, 0, 19,
+ 0, 16, 0, 13, 0, 11, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 2, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 123, 0, 115, 0, 108, 0, 102, 0, 95, 0, 89, 0, 83,
+ 0, 78, 0, 73, 0, 68, 0, 63, 0, 59, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39,
+ 0, 36, 0, 33, 0, 30, 0, 26, 0, 24, 0, 21, 0, 18, 0, 15, 0, 13, 0, 10,
+ 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 115, 0, 108, 0, 102, 0, 95, 0, 89, 0, 83, 0, 78, 0, 73, 0, 68, 0, 63, 0,
+ 59, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 33, 0, 30, 0, 26, 0,
+ 24, 0, 21, 0, 18, 0, 15, 0, 13, 0, 10, 0, 8, 0, 6, 0, 4, 0, 2, 0,
+ 0, 0, 1, 0, 0, 123, 0, 115, 0, 108, 0, 102, 0, 95, 0, 89, 0, 83, 0, 78,
+ 0, 73, 0, 68, 0, 63, 0, 59, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36,
+ 0, 33, 0, 30, 0, 26, 0, 24, 0, 21, 0, 18, 0, 15, 0, 13, 0, 10, 0, 8,
+ 0, 6, 0, 4, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 116,
+ 0, 109, 0, 102, 0, 96, 0, 90, 0, 85, 0, 79, 0, 74, 0, 69, 0, 65, 0, 60,
+ 0, 56, 0, 52, 0, 48, 0, 45, 0, 41, 0, 38, 0, 35, 0, 31, 0, 28, 0, 25,
+ 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 10, 0, 8, 0, 6, 0, 4, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 116, 0, 109, 0, 102, 0, 96, 0, 90, 0,
+ 85, 0, 79, 0, 74, 0, 69, 0, 65, 0, 60, 0, 56, 0, 52, 0, 48, 0, 45, 0,
+ 41, 0, 38, 0, 35, 0, 31, 0, 28, 0, 25, 0, 23, 0, 20, 0, 17, 0, 15, 0,
+ 12, 0, 10, 0, 8, 0, 6, 0, 4, 0, 1, 0, 0, 0, 0, 123, 0, 116, 0, 109,
+ 0, 102, 0, 96, 0, 90, 0, 85, 0, 79, 0, 74, 0, 69, 0, 65, 0, 60, 0, 56,
+ 0, 52, 0, 48, 0, 45, 0, 41, 0, 38, 0, 35, 0, 31, 0, 28, 0, 25, 0, 23,
+ 0, 20, 0, 17, 0, 15, 0, 12, 0, 10, 0, 8, 0, 6, 0, 4, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 31, 31, 63, 0, 85, 0, 95, 0, 102, 0, 106, 0, 109, 0,
+ 111, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0, 119, 0, 119, 0,
+ 120, 0,
+ 120, 0, 120, 0, 121, 0, 121, 0, 121, 0, 121, 0, 122, 0, 122, 0, 122, 0,
+ 122, 0,
+ 122, 0, 123, 0, 123, 0, 123, 0, 123, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31,
+ 0, 63, 0, 85, 0, 95, 0, 102, 0, 106, 0, 109, 0, 111, 0, 113, 0, 114, 0,
+ 115,
+ 0, 116, 0, 117, 0, 118, 0, 119, 0, 119, 0, 120, 0, 120, 0, 120, 0, 121, 0,
+ 121,
+ 0, 121, 0, 121, 0, 122, 0, 122, 0, 122, 0, 122, 0, 122, 0, 123, 0, 123, 0,
+ 123,
+ 0, 123, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 10, 10,
+ 31, 0, 51, 0, 63, 0, 72, 0, 79, 0, 85, 0, 89, 0, 92, 0, 95, 0, 98, 0,
+ 100, 0, 102, 0, 103, 0, 105, 0, 106, 0, 107, 0, 108, 0, 109, 0, 110, 0,
+ 110, 0,
+ 111, 0, 112, 0, 112, 0, 113, 0, 113, 0, 114, 0, 114, 0, 115, 0, 115, 0,
+ 115, 0,
+ 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 10, 10, 0, 31, 0, 51, 0, 63, 0, 72,
+ 0, 79, 0, 85, 0, 89, 0, 92, 0, 95, 0, 98, 0, 100, 0, 102, 0, 103, 0, 105,
+ 0, 106, 0, 107, 0, 108, 0, 109, 0, 110, 0, 110, 0, 111, 0, 112, 0, 112, 0,
+ 113,
+ 0, 113, 0, 114, 0, 114, 0, 115, 0, 115, 0, 115, 0, 116, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 85, 0, 31, 6, 6, 21, 0, 36, 0, 47, 0, 56, 0,
+ 63, 0, 69, 0, 74, 0, 78, 0, 81, 0, 85, 0, 87, 0, 89, 0, 92, 0, 93, 0,
+ 95, 0, 97, 0, 98, 0, 99, 0, 100, 0, 102, 0, 102, 0, 103, 0, 104, 0, 105, 0,
+ 106, 0, 106, 0, 107, 0, 108, 0, 108, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 0,
+ 31, 0, 6, 6, 0, 21, 0, 36, 0, 47, 0, 56, 0, 63, 0, 69, 0, 74, 0, 78,
+ 0, 81, 0, 85, 0, 87, 0, 89, 0, 92, 0, 93, 0, 95, 0, 97, 0, 98, 0, 99,
+ 0, 100, 0, 102, 0, 102, 0, 103, 0, 104, 0, 105, 0, 106, 0, 106, 0, 107, 0,
+ 108,
+ 0, 108, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 51,
+ 0, 21, 4, 4, 15, 0, 28, 0, 38, 0, 46, 0, 53, 0, 58, 0, 63, 0, 68, 0,
+ 71, 0, 75, 0, 77, 0, 80, 0, 82, 0, 85, 0, 86, 0, 88, 0, 90, 0, 91, 0,
+ 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0,
+ 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 51, 0, 21, 0, 4, 4, 0, 15, 0, 28,
+ 0, 38, 0, 46, 0, 53, 0, 58, 0, 63, 0, 68, 0, 71, 0, 75, 0, 77, 0, 80,
+ 0, 82, 0, 85, 0, 86, 0, 88, 0, 90, 0, 91, 0, 93, 0, 94, 0, 95, 0, 96,
+ 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 102, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 102, 0, 63, 0, 36, 0, 15, 3, 3, 12, 0, 23, 0,
+ 31, 0, 39, 0, 45, 0, 51, 0, 55, 0, 60, 0, 63, 0, 67, 0, 70, 0, 72, 0,
+ 75, 0, 77, 0, 79, 0, 81, 0, 83, 0, 85, 0, 86, 0, 87, 0, 89, 0, 90, 0,
+ 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 0,
+ 63, 0, 36, 0, 15, 0, 3, 3, 0, 12, 0, 23, 0, 31, 0, 39, 0, 45, 0, 51,
+ 0, 55, 0, 60, 0, 63, 0, 67, 0, 70, 0, 72, 0, 75, 0, 77, 0, 79, 0, 81,
+ 0, 83, 0, 85, 0, 86, 0, 87, 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94,
+ 0, 95, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 72,
+ 0, 47, 0, 28, 0, 12, 2, 2, 10, 0, 19, 0, 27, 0, 34, 0, 39, 0, 44, 0,
+ 49, 0, 53, 0, 57, 0, 60, 0, 63, 0, 66, 0, 69, 0, 71, 0, 73, 0, 75, 0,
+ 77, 0, 79, 0, 80, 0, 82, 0, 83, 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0,
+ 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 72, 0, 47, 0, 28, 0, 12, 0, 2, 2,
+ 0, 10, 0, 19, 0, 27, 0, 34, 0, 39, 0, 44, 0, 49, 0, 53, 0, 57, 0, 60,
+ 0, 63, 0, 66, 0, 69, 0, 71, 0, 73, 0, 75, 0, 77, 0, 79, 0, 80, 0, 82,
+ 0, 83, 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 109, 0, 79, 0, 56, 0, 38, 0, 23, 0, 10, 2, 2,
+ 9, 0, 17, 0, 23, 0, 30, 0, 35, 0, 40, 0, 44, 0, 48, 0, 52, 0, 55, 0,
+ 58, 0, 61, 0, 63, 0, 66, 0, 68, 0, 70, 0, 72, 0, 74, 0, 75, 0, 77, 0,
+ 78, 0, 80, 0, 81, 0, 82, 0, 83, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 0,
+ 79, 0, 56, 0, 38, 0, 23, 0, 10, 0, 2, 2, 0, 9, 0, 17, 0, 23, 0, 30,
+ 0, 35, 0, 40, 0, 44, 0, 48, 0, 52, 0, 55, 0, 58, 0, 61, 0, 63, 0, 66,
+ 0, 68, 0, 70, 0, 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 80, 0, 81, 0, 82,
+ 0, 83, 0, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 85,
+ 0, 63, 0, 46, 0, 31, 0, 19, 0, 9, 2, 2, 7, 0, 15, 0, 21, 0, 26, 0,
+ 31, 0, 36, 0, 40, 0, 44, 0, 47, 0, 51, 0, 53, 0, 56, 0, 59, 0, 61, 0,
+ 63, 0, 65, 0, 67, 0, 69, 0, 71, 0, 72, 0, 74, 0, 75, 0, 77, 0, 78, 0,
+ 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 85, 0, 63, 0, 46, 0, 31, 0, 19, 0,
+ 9, 0, 2, 2, 0, 7, 0, 15, 0, 21, 0, 26, 0, 31, 0, 36, 0, 40, 0, 44,
+ 0, 47, 0, 51, 0, 53, 0, 56, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 69,
+ 0, 71, 0, 72, 0, 74, 0, 75, 0, 77, 0, 78, 0, 79, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 113, 0, 89, 0, 69, 0, 53, 0, 39, 0, 27, 0, 17,
+ 0, 7, 1, 1, 7, 0, 13, 0, 19, 0, 24, 0, 28, 0, 33, 0, 37, 0, 40, 0,
+ 44, 0, 47, 0, 50, 0, 52, 0, 55, 0, 57, 0, 59, 0, 61, 0, 63, 0, 65, 0,
+ 67, 0, 68, 0, 70, 0, 71, 0, 73, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113, 0,
+ 89, 0, 69, 0, 53, 0, 39, 0, 27, 0, 17, 0, 7, 0, 1, 1, 0, 7, 0, 13,
+ 0, 19, 0, 24, 0, 28, 0, 33, 0, 37, 0, 40, 0, 44, 0, 47, 0, 50, 0, 52,
+ 0, 55, 0, 57, 0, 59, 0, 61, 0, 63, 0, 65, 0, 67, 0, 68, 0, 70, 0, 71,
+ 0, 73, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 0, 92,
+ 0, 74, 0, 58, 0, 45, 0, 34, 0, 23, 0, 15, 0, 7, 1, 1, 6, 0, 12, 0,
+ 17, 0, 22, 0, 26, 0, 30, 0, 34, 0, 37, 0, 40, 0, 43, 0, 46, 0, 49, 0,
+ 51, 0, 54, 0, 56, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0, 66, 0, 68, 0,
+ 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 114, 0, 92, 0, 74, 0, 58, 0, 45, 0, 34, 0,
+ 23, 0, 15, 0, 7, 0, 1, 1, 0, 6, 0, 12, 0, 17, 0, 22, 0, 26, 0, 30,
+ 0, 34, 0, 37, 0, 40, 0, 43, 0, 46, 0, 49, 0, 51, 0, 54, 0, 56, 0, 58,
+ 0, 60, 0, 62, 0, 63, 0, 65, 0, 66, 0, 68, 0, 69, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 115, 0, 95, 0, 78, 0, 63, 0, 51, 0, 39, 0, 30,
+ 0, 21, 0, 13, 0, 6, 1, 1, 5, 0, 11, 0, 15, 0, 20, 0, 24, 0, 28, 0,
+ 31, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48, 0, 51, 0, 53, 0, 55, 0,
+ 57, 0, 58, 0, 60, 0, 62, 0, 63, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 0,
+ 95, 0, 78, 0, 63, 0, 51, 0, 39, 0, 30, 0, 21, 0, 13, 0, 6, 0, 1, 1,
+ 0, 5, 0, 11, 0, 15, 0, 20, 0, 24, 0, 28, 0, 31, 0, 35, 0, 38, 0, 41,
+ 0, 43, 0, 46, 0, 48, 0, 51, 0, 53, 0, 55, 0, 57, 0, 58, 0, 60, 0, 62,
+ 0, 63, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 98,
+ 0, 81, 0, 68, 0, 55, 0, 44, 0, 35, 0, 26, 0, 19, 0, 12, 0, 5, 1, 1,
+ 5, 0, 10, 0, 14, 0, 18, 0, 22, 0, 26, 0, 29, 0, 32, 0, 35, 0, 38, 0,
+ 41, 0, 43, 0, 46, 0, 48, 0, 50, 0, 52, 0, 54, 0, 55, 0, 57, 0, 59, 0,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 98, 0, 81, 0, 68, 0, 55, 0, 44, 0,
+ 35, 0, 26, 0, 19, 0, 12, 0, 5, 0, 1, 1, 0, 5, 0, 10, 0, 14, 0, 18,
+ 0, 22, 0, 26, 0, 29, 0, 32, 0, 35, 0, 38, 0, 41, 0, 43, 0, 46, 0, 48,
+ 0, 50, 0, 52, 0, 54, 0, 55, 0, 57, 0, 59, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 117, 0, 100, 0, 85, 0, 71, 0, 60, 0, 49, 0, 40,
+ 0, 31, 0, 24, 0, 17, 0, 11, 0, 5, 1, 1, 4, 0, 9, 0, 13, 0, 17, 0,
+ 21, 0, 24, 0, 27, 0, 30, 0, 33, 0, 36, 0, 38, 0, 41, 0, 43, 0, 45, 0,
+ 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0,
+ 100, 0, 85, 0, 71, 0, 60, 0, 49, 0, 40, 0, 31, 0, 24, 0, 17, 0, 11, 0,
+ 5, 0, 1, 1, 0, 4, 0, 9, 0, 13, 0, 17, 0, 21, 0, 24, 0, 27, 0, 30,
+ 0, 33, 0, 36, 0, 38, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 53,
+ 0, 55, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, 102,
+ 0, 87, 0, 75, 0, 63, 0, 53, 0, 44, 0, 36, 0, 28, 0, 22, 0, 15, 0, 10,
+ 0, 4, 1, 1, 4, 0, 8, 0, 12, 0, 16, 0, 19, 0, 23, 0, 26, 0, 29, 0,
+ 31, 0, 34, 0, 36, 0, 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0,
+ 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 118, 0, 102, 0, 87, 0, 75, 0, 63, 0, 53, 0,
+ 44, 0, 36, 0, 28, 0, 22, 0, 15, 0, 10, 0, 4, 0, 1, 1, 0, 4, 0, 8,
+ 0, 12, 0, 16, 0, 19, 0, 23, 0, 26, 0, 29, 0, 31, 0, 34, 0, 36, 0, 39,
+ 0, 41, 0, 43, 0, 45, 0, 47, 0, 49, 0, 51, 0, 52, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 119, 0, 103, 0, 89, 0, 77, 0, 67, 0, 57, 0, 48,
+ 0, 40, 0, 33, 0, 26, 0, 20, 0, 14, 0, 9, 0, 4, 1, 1, 4, 0, 8, 0,
+ 11, 0, 15, 0, 18, 0, 21, 0, 24, 0, 27, 0, 30, 0, 32, 0, 35, 0, 37, 0,
+ 39, 0, 41, 0, 43, 0, 45, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0,
+ 103, 0, 89, 0, 77, 0, 67, 0, 57, 0, 48, 0, 40, 0, 33, 0, 26, 0, 20, 0,
+ 14, 0, 9, 0, 4, 0, 1, 1, 0, 4, 0, 8, 0, 11, 0, 15, 0, 18, 0, 21,
+ 0, 24, 0, 27, 0, 30, 0, 32, 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45,
+ 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 105,
+ 0, 92, 0, 80, 0, 70, 0, 60, 0, 52, 0, 44, 0, 37, 0, 30, 0, 24, 0, 18,
+ 0, 13, 0, 8, 0, 4, 1, 1, 3, 0, 7, 0, 11, 0, 14, 0, 17, 0, 20, 0,
+ 23, 0, 26, 0, 28, 0, 31, 0, 33, 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0,
+ 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 105, 0, 92, 0, 80, 0, 70, 0, 60, 0,
+ 52, 0, 44, 0, 37, 0, 30, 0, 24, 0, 18, 0, 13, 0, 8, 0, 4, 0, 1, 1,
+ 0, 3, 0, 7, 0, 11, 0, 14, 0, 17, 0, 20, 0, 23, 0, 26, 0, 28, 0, 31,
+ 0, 33, 0, 35, 0, 37, 0, 39, 0, 41, 0, 43, 0, 45, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 120, 0, 106, 0, 93, 0, 82, 0, 72, 0, 63, 0, 55,
+ 0, 47, 0, 40, 0, 34, 0, 28, 0, 22, 0, 17, 0, 12, 0, 8, 0, 3, 0, 0,
+ 3, 0, 7, 0, 10, 0, 13, 0, 16, 0, 19, 0, 22, 0, 24, 0, 27, 0, 29, 0,
+ 31, 0, 34, 0, 36, 0, 37, 0, 39, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0,
+ 106, 0, 93, 0, 82, 0, 72, 0, 63, 0, 55, 0, 47, 0, 40, 0, 34, 0, 28, 0,
+ 22, 0, 17, 0, 12, 0, 8, 0, 3, 0, 0, 0, 0, 3, 0, 7, 0, 10, 0, 13,
+ 0, 16, 0, 19, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31, 0, 34, 0, 36, 0, 37,
+ 0, 39, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 107,
+ 0, 95, 0, 85, 0, 75, 0, 66, 0, 58, 0, 51, 0, 44, 0, 37, 0, 31, 0, 26,
+ 0, 21, 0, 16, 0, 11, 0, 7, 0, 3, 0, 0, 3, 0, 6, 0, 10, 0, 13, 0,
+ 15, 0, 18, 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 32, 0, 34, 0, 36, 0,
+ 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 107, 0, 95, 0, 85, 0, 75, 0, 66, 0,
+ 58, 0, 51, 0, 44, 0, 37, 0, 31, 0, 26, 0, 21, 0, 16, 0, 11, 0, 7, 0,
+ 3, 0, 0, 0, 0, 3, 0, 6, 0, 10, 0, 13, 0, 15, 0, 18, 0, 21, 0, 23,
+ 0, 26, 0, 28, 0, 30, 0, 32, 0, 34, 0, 36, 0, 38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 120, 0, 108, 0, 97, 0, 86, 0, 77, 0, 69, 0, 61,
+ 0, 53, 0, 47, 0, 40, 0, 35, 0, 29, 0, 24, 0, 19, 0, 15, 0, 11, 0, 7,
+ 0, 3, 0, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 17, 0, 20, 0, 22, 0,
+ 24, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0,
+ 108, 0, 97, 0, 86, 0, 77, 0, 69, 0, 61, 0, 53, 0, 47, 0, 40, 0, 35, 0,
+ 29, 0, 24, 0, 19, 0, 15, 0, 11, 0, 7, 0, 3, 0, 0, 0, 0, 3, 0, 6,
+ 0, 9, 0, 12, 0, 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 27, 0, 29, 0, 31,
+ 0, 33, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 109,
+ 0, 98, 0, 88, 0, 79, 0, 71, 0, 63, 0, 56, 0, 50, 0, 43, 0, 38, 0, 32,
+ 0, 27, 0, 23, 0, 18, 0, 14, 0, 10, 0, 6, 0, 3, 0, 0, 3, 0, 6, 0,
+ 9, 0, 11, 0, 14, 0, 17, 0, 19, 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0,
+ 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 109, 0, 98, 0, 88, 0, 79, 0, 71, 0,
+ 63, 0, 56, 0, 50, 0, 43, 0, 38, 0, 32, 0, 27, 0, 23, 0, 18, 0, 14, 0,
+ 10, 0, 6, 0, 3, 0, 0, 0, 0, 3, 0, 6, 0, 9, 0, 11, 0, 14, 0, 17,
+ 0, 19, 0, 21, 0, 23, 0, 26, 0, 28, 0, 30, 0, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 121, 0, 110, 0, 99, 0, 90, 0, 81, 0, 73, 0, 66,
+ 0, 59, 0, 52, 0, 46, 0, 41, 0, 35, 0, 30, 0, 26, 0, 21, 0, 17, 0, 13,
+ 0, 10, 0, 6, 0, 3, 0, 0, 3, 0, 5, 0, 8, 0, 11, 0, 13, 0, 16, 0,
+ 18, 0, 20, 0, 22, 0, 25, 0, 26, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 110, 0, 99, 0, 90, 0, 81, 0, 73, 0, 66, 0, 59, 0, 52, 0, 46, 0, 41, 0,
+ 35, 0, 30, 0, 26, 0, 21, 0, 17, 0, 13, 0, 10, 0, 6, 0, 3, 0, 0, 0,
+ 0, 3, 0, 5, 0, 8, 0, 11, 0, 13, 0, 16, 0, 18, 0, 20, 0, 22, 0, 25,
+ 0, 26, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 110,
+ 0, 100, 0, 91, 0, 83, 0, 75, 0, 68, 0, 61, 0, 55, 0, 49, 0, 43, 0, 38,
+ 0, 33, 0, 29, 0, 24, 0, 20, 0, 16, 0, 13, 0, 9, 0, 6, 0, 3, 0, 0,
+ 2, 0, 5, 0, 8, 0, 10, 0, 13, 0, 15, 0, 17, 0, 20, 0, 22, 0, 24, 0,
+ 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 110, 0, 100, 0, 91, 0, 83, 0, 75, 0,
+ 68, 0, 61, 0, 55, 0, 49, 0, 43, 0, 38, 0, 33, 0, 29, 0, 24, 0, 20, 0,
+ 16, 0, 13, 0, 9, 0, 6, 0, 3, 0, 0, 0, 0, 2, 0, 5, 0, 8, 0, 10,
+ 0, 13, 0, 15, 0, 17, 0, 20, 0, 22, 0, 24, 0, 25, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 121, 0, 111, 0, 102, 0, 93, 0, 85, 0, 77, 0, 70,
+ 0, 63, 0, 57, 0, 51, 0, 46, 0, 41, 0, 36, 0, 31, 0, 27, 0, 23, 0, 19,
+ 0, 15, 0, 12, 0, 9, 0, 5, 0, 2, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0,
+ 12, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0,
+ 111, 0, 102, 0, 93, 0, 85, 0, 77, 0, 70, 0, 63, 0, 57, 0, 51, 0, 46, 0,
+ 41, 0, 36, 0, 31, 0, 27, 0, 23, 0, 19, 0, 15, 0, 12, 0, 9, 0, 5, 0,
+ 2, 0, 0, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 15, 0, 17, 0, 19,
+ 0, 21, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 112,
+ 0, 102, 0, 94, 0, 86, 0, 79, 0, 72, 0, 65, 0, 59, 0, 54, 0, 48, 0, 43,
+ 0, 38, 0, 34, 0, 30, 0, 26, 0, 22, 0, 18, 0, 15, 0, 11, 0, 8, 0, 5,
+ 0, 2, 0, 0, 2, 0, 5, 0, 7, 0, 10, 0, 12, 0, 14, 0, 16, 0, 18, 0,
+ 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 112, 0, 102, 0, 94, 0, 86, 0, 79, 0,
+ 72, 0, 65, 0, 59, 0, 54, 0, 48, 0, 43, 0, 38, 0, 34, 0, 30, 0, 26, 0,
+ 22, 0, 18, 0, 15, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 5,
+ 0, 7, 0, 10, 0, 12, 0, 14, 0, 16, 0, 18, 0, 20, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 122, 0, 112, 0, 103, 0, 95, 0, 87, 0, 80, 0, 74,
+ 0, 67, 0, 61, 0, 56, 0, 51, 0, 46, 0, 41, 0, 36, 0, 32, 0, 28, 0, 24,
+ 0, 21, 0, 17, 0, 14, 0, 11, 0, 8, 0, 5, 0, 2, 0, 0, 2, 0, 5, 0,
+ 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 112, 0, 103, 0, 95, 0, 87, 0, 80, 0, 74, 0, 67, 0, 61, 0, 56, 0, 51, 0,
+ 46, 0, 41, 0, 36, 0, 32, 0, 28, 0, 24, 0, 21, 0, 17, 0, 14, 0, 11, 0,
+ 8, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13,
+ 0, 15, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 113,
+ 0, 104, 0, 96, 0, 89, 0, 82, 0, 75, 0, 69, 0, 63, 0, 58, 0, 53, 0, 48,
+ 0, 43, 0, 39, 0, 35, 0, 31, 0, 27, 0, 23, 0, 20, 0, 17, 0, 13, 0, 10,
+ 0, 7, 0, 5, 0, 2, 0, 0, 2, 0, 4, 0, 7, 0, 9, 0, 11, 0, 13, 0,
+ 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 113, 0, 104, 0, 96, 0, 89, 0, 82, 0,
+ 75, 0, 69, 0, 63, 0, 58, 0, 53, 0, 48, 0, 43, 0, 39, 0, 35, 0, 31, 0,
+ 27, 0, 23, 0, 20, 0, 17, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 0,
+ 0, 2, 0, 4, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 122, 0, 113, 0, 105, 0, 97, 0, 90, 0, 83, 0, 77,
+ 0, 71, 0, 65, 0, 60, 0, 55, 0, 50, 0, 45, 0, 41, 0, 37, 0, 33, 0, 29,
+ 0, 26, 0, 22, 0, 19, 0, 16, 0, 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0,
+ 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0,
+ 113, 0, 105, 0, 97, 0, 90, 0, 83, 0, 77, 0, 71, 0, 65, 0, 60, 0, 55, 0,
+ 50, 0, 45, 0, 41, 0, 37, 0, 33, 0, 29, 0, 26, 0, 22, 0, 19, 0, 16, 0,
+ 13, 0, 10, 0, 7, 0, 5, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8,
+ 0, 10, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 114,
+ 0, 106, 0, 98, 0, 91, 0, 85, 0, 78, 0, 72, 0, 67, 0, 62, 0, 57, 0, 52,
+ 0, 47, 0, 43, 0, 39, 0, 35, 0, 31, 0, 28, 0, 24, 0, 21, 0, 18, 0, 15,
+ 0, 12, 0, 10, 0, 7, 0, 4, 0, 2, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0,
+ 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 0, 114, 0, 106, 0, 98, 0, 91, 0, 85, 0,
+ 78, 0, 72, 0, 67, 0, 62, 0, 57, 0, 52, 0, 47, 0, 43, 0, 39, 0, 35, 0,
+ 31, 0, 28, 0, 24, 0, 21, 0, 18, 0, 15, 0, 12, 0, 10, 0, 7, 0, 4, 0,
+ 2, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 114, 0, 106, 0, 99, 0, 92, 0, 86, 0, 80,
+ 0, 74, 0, 68, 0, 63, 0, 58, 0, 54, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34,
+ 0, 30, 0, 27, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 9, 0, 7, 0, 4,
+ 0, 2, 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 114, 0, 106, 0, 99, 0, 92, 0, 86, 0, 80, 0, 74, 0, 68, 0, 63, 0, 58, 0,
+ 54, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 30, 0, 27, 0, 23, 0, 20, 0,
+ 17, 0, 15, 0, 12, 0, 9, 0, 7, 0, 4, 0, 2, 0, 0, 0, 0, 2, 0, 4,
+ 0, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115,
+ 0, 107, 0, 100, 0, 93, 0, 87, 0, 81, 0, 75, 0, 70, 0, 65, 0, 60, 0, 55,
+ 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 32, 0, 29, 0, 26, 0, 22, 0, 20,
+ 0, 17, 0, 14, 0, 11, 0, 9, 0, 6, 0, 4, 0, 2, 0, 0, 2, 0, 4, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 107, 0, 100, 0, 93, 0, 87, 0,
+ 81, 0, 75, 0, 70, 0, 65, 0, 60, 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0,
+ 36, 0, 32, 0, 29, 0, 26, 0, 22, 0, 20, 0, 17, 0, 14, 0, 11, 0, 9, 0,
+ 6, 0, 4, 0, 2, 0, 0, 0, 0, 2, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 108, 0, 101, 0, 94, 0, 88, 0, 82,
+ 0, 77, 0, 71, 0, 66, 0, 62, 0, 57, 0, 53, 0, 49, 0, 45, 0, 41, 0, 37,
+ 0, 34, 0, 31, 0, 28, 0, 25, 0, 22, 0, 19, 0, 16, 0, 13, 0, 11, 0, 8,
+ 0, 6, 0, 4, 0, 2, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 115, 0, 108, 0, 101, 0, 94, 0, 88, 0, 82, 0, 77, 0, 71, 0, 66, 0, 62, 0,
+ 57, 0, 53, 0, 49, 0, 45, 0, 41, 0, 37, 0, 34, 0, 31, 0, 28, 0, 25, 0,
+ 22, 0, 19, 0, 16, 0, 13, 0, 11, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 0,
+ 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115,
+ 0, 108, 0, 102, 0, 95, 0, 89, 0, 83, 0, 78, 0, 73, 0, 68, 0, 63, 0, 59,
+ 0, 55, 0, 51, 0, 47, 0, 43, 0, 39, 0, 36, 0, 33, 0, 30, 0, 26, 0, 24,
+ 0, 21, 0, 18, 0, 15, 0, 13, 0, 10, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 115, 0, 108, 0, 102, 0, 95, 0, 89, 0,
+ 83, 0, 78, 0, 73, 0, 68, 0, 63, 0, 59, 0, 55, 0, 51, 0, 47, 0, 43, 0,
+ 39, 0, 36, 0, 33, 0, 30, 0, 26, 0, 24, 0, 21, 0, 18, 0, 15, 0, 13, 0,
+ 10, 0, 8, 0, 6, 0, 4, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 116, 0, 109, 0, 102, 0, 96, 0, 90, 0, 85,
+ 0, 79, 0, 74, 0, 69, 0, 65, 0, 60, 0, 56, 0, 52, 0, 48, 0, 45, 0, 41,
+ 0, 38, 0, 35, 0, 31, 0, 28, 0, 25, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12,
+ 0, 10, 0, 8, 0, 6, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0,
+ 116, 0, 109, 0, 102, 0, 96, 0, 90, 0, 85, 0, 79, 0, 74, 0, 69, 0, 65, 0,
+ 60, 0, 56, 0, 52, 0, 48, 0, 45, 0, 41, 0, 38, 0, 35, 0, 31, 0, 28, 0,
+ 25, 0, 23, 0, 20, 0, 17, 0, 15, 0, 12, 0, 10, 0, 8, 0, 6, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/pp_program.c b/src/gallium/auxiliary/postprocess/pp_program.c
new file mode 100644
index 00000000000..b92ac80a5db
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_program.c
@@ -0,0 +1,139 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Jakob Bornecrantz
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "postprocess/postprocess.h"
+#include "cso_cache/cso_context.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+#include "util/u_inlines.h"
+#include "util/u_simple_shaders.h"
+
+/** Initialize the internal details */
+struct program *
+pp_init_prog(struct pp_queue_t *ppq, struct pipe_screen *pscreen)
+{
+
+ struct program *p = calloc(1, sizeof(struct program));
+
+ pp_debug("Initializing program\n");
+ if (!pscreen)
+ return NULL;
+
+ if (!p)
+ return NULL;
+
+ p->screen = pscreen;
+ p->pipe = pscreen->context_create(pscreen, NULL);
+ p->cso = cso_create_context(p->pipe);
+
+ {
+ static const float verts[4][2][4] = {
+ {
+ {1.0f, 1.0f, 0.0f, 1.0f},
+ {1.0f, 1.0f, 0.0f, 1.0f}
+ },
+ {
+ {-1.0f, 1.0f, 0.0f, 1.0f},
+ {0.0f, 1.0f, 0.0f, 1.0f}
+ },
+ {
+ {-1.0f, -1.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}
+ },
+ {
+ {1.0f, -1.0f, 0.0f, 1.0f},
+ {1.0f, 0.0f, 0.0f, 1.0f}
+ }
+ };
+
+ p->vbuf = pipe_buffer_create(pscreen, PIPE_BIND_VERTEX_BUFFER,
+ PIPE_USAGE_STATIC, sizeof(verts));
+ pipe_buffer_write(p->pipe, p->vbuf, 0, sizeof(verts), verts);
+ }
+
+ p->blend.rt[0].colormask = PIPE_MASK_RGBA;
+ p->blend.rt[0].rgb_src_factor = p->blend.rt[0].alpha_src_factor =
+ PIPE_BLENDFACTOR_SRC_ALPHA;
+ p->blend.rt[0].rgb_dst_factor = p->blend.rt[0].alpha_dst_factor =
+ PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+
+ p->rasterizer.cull_face = PIPE_FACE_NONE;
+ p->rasterizer.gl_rasterization_rules = 1;
+
+ p->sampler.wrap_s = p->sampler.wrap_t = p->sampler.wrap_r =
+ PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+
+ p->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ p->sampler.min_img_filter = p->sampler.mag_img_filter =
+ PIPE_TEX_FILTER_LINEAR;
+ p->sampler.normalized_coords = 1;
+
+ p->sampler_point.wrap_s = p->sampler_point.wrap_t =
+ p->sampler_point.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ p->sampler_point.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ p->sampler_point.min_img_filter = p->sampler_point.mag_img_filter =
+ PIPE_TEX_FILTER_NEAREST;
+ p->sampler_point.normalized_coords = 1;
+
+ p->velem[0].src_offset = 0;
+ p->velem[0].instance_divisor = 0;
+ p->velem[0].vertex_buffer_index = 0;
+ p->velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ p->velem[1].src_offset = 1 * 4 * sizeof(float);
+ p->velem[1].instance_divisor = 0;
+ p->velem[1].vertex_buffer_index = 0;
+ p->velem[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+
+ if (!p->screen->is_format_supported(p->screen,
+ PIPE_FORMAT_R32G32B32A32_FLOAT,
+ PIPE_BUFFER, 1,
+ PIPE_BIND_VERTEX_BUFFER))
+ pp_debug("Vertex buf format fail\n");
+
+
+ {
+ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
+ TGSI_SEMANTIC_GENERIC
+ };
+ const uint semantic_indexes[] = { 0, 0 };
+ p->passvs = util_make_vertex_passthrough_shader(p->pipe, 2,
+ semantic_names,
+ semantic_indexes);
+ }
+
+ p->framebuffer.nr_cbufs = 1;
+
+ p->surf.usage = PIPE_BIND_RENDER_TARGET;
+ p->surf.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+
+ p->pipe->set_sample_mask(p->pipe, ~0);
+
+ return p;
+}
diff --git a/src/gallium/auxiliary/postprocess/pp_program.h b/src/gallium/auxiliary/postprocess/pp_program.h
new file mode 100644
index 00000000000..2749b35b372
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_program.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Jakob Bornecrantz
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef PP_PROGRAM_H
+#define PP_PROGRAM_H
+
+#include "pipe/p_state.h"
+
+/**
+* Internal control details.
+*/
+struct program
+{
+ struct pipe_screen *screen;
+ struct pipe_context *pipe;
+ struct cso_context *cso;
+
+ struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state depthstencil;
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_sampler_state sampler; /* bilinear */
+ struct pipe_sampler_state sampler_point; /* point */
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_vertex_element velem[2];
+
+ float clear_color[4];
+
+ void *passvs;
+
+ struct pipe_resource *vbuf;
+ struct pipe_surface surf;
+ struct pipe_sampler_view *view;
+
+ struct blit_state *blitctx;
+};
+
+
+#endif
diff --git a/src/gallium/auxiliary/postprocess/pp_run.c b/src/gallium/auxiliary/postprocess/pp_run.c
new file mode 100644
index 00000000000..ce671aea360
--- /dev/null
+++ b/src/gallium/auxiliary/postprocess/pp_run.c
@@ -0,0 +1,188 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Lauri Kasanen
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "postprocess.h"
+
+#include "postprocess/pp_filters.h"
+#include "util/u_blit.h"
+#include "util/u_inlines.h"
+#include "util/u_sampler.h"
+
+/**
+* Main run function of the PP queue. Called on swapbuffers/flush.
+*
+* Runs all requested filters in order and handles shuffling the temp
+* buffers in between.
+*/
+void
+pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
+ struct pipe_resource *out, struct pipe_resource *indepth)
+{
+
+ unsigned int i;
+
+ if (in->width0 != ppq->p->framebuffer.width ||
+ in->height0 != ppq->p->framebuffer.height) {
+ pp_debug("Resizing the temp pp buffers\n");
+ pp_free_fbos(ppq);
+ pp_init_fbos(ppq, in->width0, in->height0, indepth);
+ }
+
+ if (in == out && ppq->n_filters == 1) {
+ /* Make a copy of in to tmp[0] in this case. */
+ unsigned int w = ppq->p->framebuffer.width;
+ unsigned int h = ppq->p->framebuffer.height;
+
+ util_blit_pixels(ppq->p->blitctx, in, 0, 0, 0,
+ w, h, 0, ppq->tmps[0],
+ 0, 0, w, h, 0, PIPE_TEX_MIPFILTER_NEAREST);
+
+ in = ppq->tmp[0];
+ }
+
+ switch (ppq->n_filters) {
+ case 1: /* No temp buf */
+ ppq->pp_queue[0] (ppq, in, out, 0);
+ break;
+ case 2: /* One temp buf */
+
+ ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
+ ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1);
+
+ break;
+ default: /* Two temp bufs */
+ ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
+
+ for (i = 1; i < (ppq->n_filters - 1); i++) {
+ if (i % 2 == 0)
+ ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i);
+
+ else
+ ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i);
+ }
+
+ if (i % 2 == 0)
+ ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i);
+
+ else
+ ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i);
+
+ break;
+ }
+}
+
+
+/* Utility functions for the filters. You're not forced to use these if */
+/* your filter is more complicated. */
+
+/** Setup this resource as the filter input. */
+void
+pp_filter_setup_in(struct program *p, struct pipe_resource *in)
+{
+ struct pipe_sampler_view v_tmp;
+ u_sampler_view_default_template(&v_tmp, in, in->format);
+ p->view = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);
+}
+
+/** Setup this resource as the filter output. */
+void
+pp_filter_setup_out(struct program *p, struct pipe_resource *out)
+{
+ p->surf.format = out->format;
+ p->surf.usage = PIPE_BIND_RENDER_TARGET;
+
+ p->framebuffer.cbufs[0] = p->pipe->create_surface(p->pipe, out, &p->surf);
+}
+
+/** Clean up the input and output set with the above. */
+void
+pp_filter_end_pass(struct program *p)
+{
+ pipe_surface_reference(&p->framebuffer.cbufs[0], NULL);
+ pipe_sampler_view_reference(&p->view, NULL);
+}
+
+/**
+* Convert the TGSI assembly to a runnable shader.
+*
+* We need not care about geometry shaders. All we have is screen quads.
+*/
+void *
+pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
+ const char *name)
+{
+ struct pipe_shader_state state;
+ struct tgsi_token tokens[PP_MAX_TOKENS];
+
+ if (tgsi_text_translate(text, tokens, Elements(tokens)) == FALSE) {
+ pp_debug("Failed to translate %s\n", name);
+ return NULL;
+ }
+
+ state.tokens = tokens;
+
+ if (isvs)
+ return pipe->create_vs_state(pipe, &state);
+ else
+ return pipe->create_fs_state(pipe, &state);
+}
+
+/** Setup misc state for the filter. */
+void
+pp_filter_misc_state(struct program *p)
+{
+ cso_set_blend(p->cso, &p->blend);
+ cso_set_depth_stencil_alpha(p->cso, &p->depthstencil);
+ cso_set_rasterizer(p->cso, &p->rasterizer);
+ cso_set_viewport(p->cso, &p->viewport);
+
+ cso_set_vertex_elements(p->cso, 2, p->velem);
+}
+
+/** Draw with the filter to the set output. */
+void
+pp_filter_draw(struct program *p)
+{
+ util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0,
+ PIPE_PRIM_QUADS, 4, 2);
+ p->pipe->flush(p->pipe, NULL);
+}
+
+/** Set the framebuffer as active. */
+void
+pp_filter_set_fb(struct program *p)
+{
+ cso_set_framebuffer(p->cso, &p->framebuffer);
+}
+
+/** Set the framebuffer as active and clear it. */
+void
+pp_filter_set_clear_fb(struct program *p)
+{
+ cso_set_framebuffer(p->cso, &p->framebuffer);
+ p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, p->clear_color, 0, 0);
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 712e8aca794..38dc1efa551 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -1594,6 +1594,9 @@ store_dest(struct tgsi_exec_machine *mach,
#define FETCH(VAL,INDEX,CHAN)\
fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_FLOAT)
+#define IFETCH(VAL,INDEX,CHAN)\
+ fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_INT)
+
/**
* Execute ARB-style KIL which is predicated by a src register.
@@ -1921,6 +1924,86 @@ exec_txd(struct tgsi_exec_machine *mach,
}
+static void
+exec_txf(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ struct tgsi_sampler *sampler;
+ const uint unit = inst->Src[1].Register.Index;
+ union tgsi_exec_channel r[4];
+ uint chan;
+ float rgba[NUM_CHANNELS][QUAD_SIZE];
+ int j;
+
+ IFETCH(&r[3], 0, CHAN_W);
+
+ switch(inst->Texture.Texture) {
+ case TGSI_TEXTURE_3D:
+ case TGSI_TEXTURE_2D_ARRAY:
+ IFETCH(&r[2], 0, CHAN_Z);
+ /* fallthrough */
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_RECT:
+ case TGSI_TEXTURE_SHADOW2D:
+ case TGSI_TEXTURE_SHADOWRECT:
+ case TGSI_TEXTURE_1D_ARRAY:
+ IFETCH(&r[1], 0, CHAN_Y);
+ /* fallthrough */
+ case TGSI_TEXTURE_1D:
+ case TGSI_TEXTURE_SHADOW1D:
+ IFETCH(&r[0], 0, CHAN_X);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ sampler = mach->Samplers[unit];
+ sampler->get_texel(sampler, r[0].i, r[1].i, r[2].i, r[3].i, rgba);
+
+ for (j = 0; j < QUAD_SIZE; j++) {
+ r[0].f[j] = rgba[0][j];
+ r[1].f[j] = rgba[1][j];
+ r[2].f[j] = rgba[2][j];
+ r[3].f[j] = rgba[3][j];
+ }
+
+ for (chan = 0; chan < NUM_CHANNELS; chan++) {
+ if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+ store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+ }
+ }
+}
+
+static void
+exec_txq(struct tgsi_exec_machine *mach,
+ const struct tgsi_full_instruction *inst)
+{
+ struct tgsi_sampler *sampler;
+ const uint unit = inst->Src[1].Register.Index;
+ int result[4];
+ union tgsi_exec_channel r[4], src;
+ uint chan;
+ int i,j;
+
+ fetch_source(mach, &src, &inst->Src[0], CHAN_X, TGSI_EXEC_DATA_INT);
+ sampler = mach->Samplers[unit];
+
+ sampler->get_dims(sampler, src.i[0], result);
+
+ for (i = 0; i < QUAD_SIZE; i++) {
+ for (j = 0; j < 4; j++) {
+ r[j].i[i] = result[j];
+ }
+ }
+
+ for (chan = 0; chan < NUM_CHANNELS; chan++) {
+ if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+ store_dest(mach, &r[chan], &inst->Dst[0], inst, chan,
+ TGSI_EXEC_DATA_INT);
+ }
+ }
+}
static void
exec_sample(struct tgsi_exec_machine *mach,
@@ -2989,6 +3072,17 @@ micro_xor(union tgsi_exec_channel *dst,
}
static void
+micro_mod(union tgsi_exec_channel *dst,
+ const union tgsi_exec_channel *src0,
+ const union tgsi_exec_channel *src1)
+{
+ dst->i[0] = src0->i[0] % src1->i[0];
+ dst->i[1] = src0->i[1] % src1->i[1];
+ dst->i[2] = src0->i[2] % src1->i[2];
+ dst->i[3] = src0->i[3] % src1->i[3];
+}
+
+static void
micro_f2i(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
@@ -3691,7 +3785,7 @@ exec_instruction(
break;
case TGSI_OPCODE_MOD:
- assert (0);
+ exec_vector_binary(mach, inst, micro_mod, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
case TGSI_OPCODE_XOR:
@@ -3703,11 +3797,11 @@ exec_instruction(
break;
case TGSI_OPCODE_TXF:
- assert (0);
+ exec_txf(mach, inst);
break;
case TGSI_OPCODE_TXQ:
- assert (0);
+ exec_txq(mach, inst);
break;
case TGSI_OPCODE_EMIT:
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index 33f33aa82c7..3f6964c17fb 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -90,6 +90,11 @@ struct tgsi_sampler
const float c0[QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[NUM_CHANNELS][QUAD_SIZE]);
+ void (*get_dims)(struct tgsi_sampler *sampler, int level,
+ int dims[4]);
+ void (*get_texel)(struct tgsi_sampler *sampler, const int i[QUAD_SIZE],
+ const int j[QUAD_SIZE], const int k[QUAD_SIZE],
+ const int lod[QUAD_SIZE], float rgba[NUM_CHANNELS][QUAD_SIZE]);
};
#define TGSI_EXEC_NUM_TEMPS 128
@@ -400,6 +405,8 @@ tgsi_exec_get_shader_param(enum pipe_shader_cap param)
return 1;
case PIPE_SHADER_CAP_SUBROUTINES:
return 1;
+ case PIPE_SHADER_CAP_INTEGERS:
+ return 1;
default:
return 0;
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.c b/src/gallium/auxiliary/tgsi/tgsi_scan.c
index 83c6ac75e54..f165f8240e6 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.c
@@ -200,19 +200,20 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
}
break;
+
case TGSI_TOKEN_TYPE_PROPERTY:
- {
- const struct tgsi_full_property *fullprop
- = &parse.FullToken.FullProperty;
+ {
+ const struct tgsi_full_property *fullprop
+ = &parse.FullToken.FullProperty;
- info->properties[info->num_properties].name =
- fullprop->Property.PropertyName;
- memcpy(info->properties[info->num_properties].data,
- fullprop->u, 8 * sizeof(unsigned));;
+ info->properties[info->num_properties].name =
+ fullprop->Property.PropertyName;
+ memcpy(info->properties[info->num_properties].data,
+ fullprop->u, 8 * sizeof(unsigned));;
- ++info->num_properties;
- }
- break;
+ ++info->num_properties;
+ }
+ break;
default:
assert( 0 );
@@ -222,6 +223,23 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
info->uses_kill = (info->opcode_count[TGSI_OPCODE_KIL] ||
info->opcode_count[TGSI_OPCODE_KILP]);
+ /* extract simple properties */
+ for (i = 0; i < info->num_properties; ++i) {
+ switch (info->properties[i].name) {
+ case TGSI_PROPERTY_FS_COORD_ORIGIN:
+ info->origin_lower_left = info->properties[i].data[0];
+ break;
+ case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
+ info->pixel_center_integer = info->properties[i].data[0];
+ break;
+ case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
+ info->color0_writes_all_cbufs = info->properties[i].data[0];
+ break;
+ default:
+ ;
+ }
+ }
+
tgsi_parse_free (&parse);
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_scan.h b/src/gallium/auxiliary/tgsi/tgsi_scan.h
index 53ab3d509dd..d6e593b3968 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_scan.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_scan.h
@@ -68,6 +68,9 @@ struct tgsi_shader_info
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
boolean uses_kill; /**< KIL or KILP instruction used? */
boolean uses_instanceid;
+ boolean origin_lower_left;
+ boolean pixel_center_integer;
+ boolean color0_writes_all_cbufs;
/**
* Bitmask indicating which register files are accessed with
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 528f344a0f7..d8e46f07c88 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -26,8 +26,8 @@
/**
* @file
- * Blitter utility to facilitate acceleration of the clear, clear_render_target, clear_depth_stencil
- * resource_copy_region functions.
+ * Blitter utility to facilitate acceleration of the clear, clear_render_target,
+ * clear_depth_stencil, and resource_copy_region functions.
*
* @author Marek Olšák
*/
@@ -197,8 +197,6 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
memset(&velem[0], 0, sizeof(velem[0]) * 2);
for (i = 0; i < 2; i++) {
velem[i].src_offset = i * 4 * sizeof(float);
- velem[i].instance_divisor = 0;
- velem[i].vertex_buffer_index = 0;
velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
}
ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
@@ -288,26 +286,33 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx)
unsigned i;
/* restore the state objects which are always required to be saved */
- pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
- pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
- pipe->bind_fs_state(pipe, ctx->base.saved_fs);
pipe->bind_vs_state(pipe, ctx->base.saved_vs);
pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
- ctx->base.saved_blend_state = INVALID_PTR;
- ctx->base.saved_dsa_state = INVALID_PTR;
ctx->base.saved_rs_state = INVALID_PTR;
- ctx->base.saved_fs = INVALID_PTR;
ctx->base.saved_vs = INVALID_PTR;
ctx->base.saved_velem_state = INVALID_PTR;
+ /* restore the state objects which are required to be saved for clear/copy
+ */
+ if (ctx->base.saved_blend_state != INVALID_PTR) {
+ pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
+ ctx->base.saved_blend_state = INVALID_PTR;
+ }
+ if (ctx->base.saved_dsa_state != INVALID_PTR) {
+ pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
+ ctx->base.saved_dsa_state = INVALID_PTR;
+ }
+ if (ctx->base.saved_fs != INVALID_PTR) {
+ pipe->bind_fs_state(pipe, ctx->base.saved_fs);
+ ctx->base.saved_fs = INVALID_PTR;
+ }
+
pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
pipe->set_clip_state(pipe, &ctx->base.saved_clip);
- /* restore the state objects which are required to be saved before copy/fill
- */
if (ctx->base.saved_fb_state.nr_cbufs != ~0) {
pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
@@ -724,14 +729,14 @@ boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2,
return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1;
}
-void util_blitter_copy_region(struct blitter_context *blitter,
- struct pipe_resource *dst,
- unsigned dstlevel,
- unsigned dstx, unsigned dsty, unsigned dstz,
- struct pipe_resource *src,
- unsigned srclevel,
- const struct pipe_box *srcbox,
- boolean ignore_stencil)
+void util_blitter_copy_texture(struct blitter_context *blitter,
+ struct pipe_resource *dst,
+ unsigned dstlevel,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src,
+ unsigned srclevel,
+ const struct pipe_box *srcbox,
+ boolean ignore_stencil)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index 41470d92bba..df6f023a638 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -126,12 +126,15 @@ struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter)
}
/*
- * These CSOs must be saved before any of the following functions is called:
+ * These states must be saved before any of the following functions is called:
* - blend state
* - depth stencil alpha state
* - rasterizer state
* - vertex shader
+ * - any other shader??? (XXX)
* - fragment shader
+ * - vertex buffers
+ * - vertex elements
*/
/**
@@ -169,14 +172,14 @@ void util_blitter_clear_depth_custom(struct blitter_context *blitter,
* - fragment sampler states
* - fragment sampler textures
*/
-void util_blitter_copy_region(struct blitter_context *blitter,
- struct pipe_resource *dst,
- unsigned dstlevel,
- unsigned dstx, unsigned dsty, unsigned dstz,
- struct pipe_resource *src,
- unsigned srclevel,
- const struct pipe_box *srcbox,
- boolean ignore_stencil);
+void util_blitter_copy_texture(struct blitter_context *blitter,
+ struct pipe_resource *dst,
+ unsigned dstlevel,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src,
+ unsigned srclevel,
+ const struct pipe_box *srcbox,
+ boolean ignore_stencil);
/**
* Clear a region of a (color) surface to a constant value.
diff --git a/src/gallium/auxiliary/util/u_debug.c b/src/gallium/auxiliary/util/u_debug.c
index 004df439ff5..2d6193039a7 100644
--- a/src/gallium/auxiliary/util/u_debug.c
+++ b/src/gallium/auxiliary/util/u_debug.c
@@ -730,7 +730,7 @@ debug_dump_float_rgba_bmp(const char *filename,
pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
- pixel.rgbAlpha = 255;
+ pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]);
os_stream_write(stream, &pixel, 4);
}
}
diff --git a/src/gallium/auxiliary/util/u_format.c b/src/gallium/auxiliary/util/u_format.c
index 9cbdd0a5b99..34922ab18ab 100644
--- a/src/gallium/auxiliary/util/u_format.c
+++ b/src/gallium/auxiliary/util/u_format.c
@@ -390,3 +390,53 @@ util_format_translate(enum pipe_format dst_format,
FREE(tmp_row);
}
}
+
+void util_format_compose_swizzles(const unsigned char swz1[4],
+ const unsigned char swz2[4],
+ unsigned char dst[4])
+{
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ?
+ swz1[swz2[i]] : swz2[i];
+ }
+}
+
+void util_format_swizzle_4f(float *dst, const float *src,
+ const unsigned char swz[4])
+{
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ if (swz[i] <= UTIL_FORMAT_SWIZZLE_W)
+ dst[i] = src[swz[i]];
+ else if (swz[i] == UTIL_FORMAT_SWIZZLE_0)
+ dst[i] = 0;
+ else if (swz[i] == UTIL_FORMAT_SWIZZLE_1)
+ dst[i] = 1;
+ }
+}
+
+void util_format_unswizzle_4f(float *dst, const float *src,
+ const unsigned char swz[4])
+{
+ unsigned i;
+
+ for (i = 0; i < 4; i++) {
+ switch (swz[i]) {
+ case UTIL_FORMAT_SWIZZLE_X:
+ dst[0] = src[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_Y:
+ dst[1] = src[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_Z:
+ dst[2] = src[i];
+ break;
+ case UTIL_FORMAT_SWIZZLE_W:
+ dst[3] = src[i];
+ break;
+ }
+ }
+}
diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv
index 347e2beb8dd..a3d2aae62c8 100644
--- a/src/gallium/auxiliary/util/u_format.csv
+++ b/src/gallium/auxiliary/util/u_format.csv
@@ -260,10 +260,10 @@ PIPE_FORMAT_R10G10B10X2_USCALED , plain, 1, 1, u10 , u10 , u10 , x2 , xyz1, r
# A.k.a. D3DDECLTYPE_DEC3N
PIPE_FORMAT_R10G10B10X2_SNORM , plain, 1, 1, sn10, sn10, sn10 , x2 , xyz1, rgb
-PIPE_FORMAT_YV12 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_YV16 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_IYUV , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_NV12 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_NV21 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_IA44 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
-PIPE_FORMAT_AI44 , subsampled, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_YV12 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_YV16 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_IYUV , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_NV12 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_NV21 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_IA44 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
+PIPE_FORMAT_AI44 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
index bb3ed72e932..566fa79e781 100644
--- a/src/gallium/auxiliary/util/u_format.h
+++ b/src/gallium/auxiliary/util/u_format.h
@@ -815,6 +815,25 @@ util_format_translate(enum pipe_format dst_format,
unsigned src_x, unsigned src_y,
unsigned width, unsigned height);
+/*
+ * Swizzle operations.
+ */
+
+/* Compose two sets of swizzles.
+ * If V is a 4D vector and the function parameters represent functions that
+ * swizzle vector components, this holds:
+ * swz2(swz1(V)) = dst(V)
+ */
+void util_format_compose_swizzles(const unsigned char swz1[4],
+ const unsigned char swz2[4],
+ unsigned char dst[4]);
+
+void util_format_swizzle_4f(float *dst, const float *src,
+ const unsigned char swz[4]);
+
+void util_format_unswizzle_4f(float *dst, const float *src,
+ const unsigned char swz[4]);
+
#ifdef __cplusplus
} // extern "C" {
#endif
diff --git a/src/gallium/auxiliary/util/u_format_s3tc.c b/src/gallium/auxiliary/util/u_format_s3tc.c
index bb989c29d81..d8a7c0d453f 100644
--- a/src/gallium/auxiliary/util/u_format_s3tc.c
+++ b/src/gallium/auxiliary/util/u_format_s3tc.c
@@ -119,8 +119,15 @@ util_format_s3tc_init(void)
library = util_dl_open(DXTN_LIBNAME);
if (!library) {
- debug_printf("couldn't open " DXTN_LIBNAME ", software DXTn "
- "compression/decompression unavailable\n");
+ if (getenv("force_s3tc_enable") &&
+ !strcmp(getenv("force_s3tc_enable"), "true")) {
+ debug_printf("couldn't open " DXTN_LIBNAME ", enabling DXTn due to "
+ "force_s3tc_enable=true environment variable\n");
+ util_format_s3tc_enabled = TRUE;
+ } else {
+ debug_printf("couldn't open " DXTN_LIBNAME ", software DXTn "
+ "compression/decompression unavailable\n");
+ }
return;
}
diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h
index 0b5284428eb..46d9322932a 100644
--- a/src/gallium/auxiliary/util/u_math.h
+++ b/src/gallium/auxiliary/util/u_math.h
@@ -199,6 +199,16 @@ roundf(float x)
#endif /* _MSC_VER */
+#ifdef PIPE_OS_ANDROID
+
+static INLINE
+double log2(double d)
+{
+ return log(d) * (1.0 / M_LN2);
+}
+
+#endif
+
@@ -409,7 +419,7 @@ unsigned ffs( unsigned u )
return i;
}
-#elif defined(__MINGW32__)
+#elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID)
#define ffs __builtin_ffs
#endif
diff --git a/src/gallium/auxiliary/util/u_pstipple.c b/src/gallium/auxiliary/util/u_pstipple.c
index f79a6938d1d..ac0df8c1a9c 100644
--- a/src/gallium/auxiliary/util/u_pstipple.c
+++ b/src/gallium/auxiliary/util/u_pstipple.c
@@ -52,6 +52,7 @@
#include "tgsi/tgsi_transform.h"
#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_scan.h"
/** Approx number of new tokens for instructions in pstip_transform_inst() */
#define NUM_NEW_TOKENS 50
@@ -175,6 +176,7 @@ util_pstipple_create_sampler(struct pipe_context *pipe)
*/
struct pstip_transform_context {
struct tgsi_transform_context base;
+ struct tgsi_shader_info info;
uint tempsUsed; /**< bitmask */
int wincoordInput;
int maxInput;
@@ -183,12 +185,13 @@ struct pstip_transform_context {
int texTemp; /**< temp registers */
int numImmed;
boolean firstInstruction;
+ uint coordOrigin;
};
/**
* TGSI declaration transform callback.
- * Look for a free sampler, a free input attrib, and two free temp regs.
+ * Track samplers used, temps used, inputs used.
*/
static void
pstip_transform_decl(struct tgsi_transform_context *ctx,
@@ -197,10 +200,11 @@ pstip_transform_decl(struct tgsi_transform_context *ctx,
struct pstip_transform_context *pctx =
(struct pstip_transform_context *) ctx;
+ /* XXX we can use tgsi_shader_info instead of some of this */
+
if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
uint i;
- for (i = decl->Range.First;
- i <= decl->Range.Last; i++) {
+ for (i = decl->Range.First; i <= decl->Range.Last; i++) {
pctx->samplersUsed |= 1 << i;
}
}
@@ -211,8 +215,7 @@ pstip_transform_decl(struct tgsi_transform_context *ctx,
}
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
uint i;
- for (i = decl->Range.First;
- i <= decl->Range.Last; i++) {
+ for (i = decl->Range.First; i <= decl->Range.Last; i++) {
pctx->tempsUsed |= (1 << i);
}
}
@@ -243,8 +246,16 @@ free_bit(uint bitfield)
/**
* TGSI instruction transform callback.
- * Replace writes to result.color w/ a temp reg.
- * Upon END instruction, insert texture sampling code for antialiasing.
+ * Before the first instruction, insert our new code to sample the
+ * stipple texture (using the fragment coord register) then kill the
+ * fragment if the stipple texture bit is off.
+ *
+ * Insert:
+ * declare new registers
+ * MUL texTemp, INPUT[wincoord], 1/32;
+ * TEX texTemp, texTemp, sampler;
+ * KIL -texTemp; # if -texTemp < 0, KILL fragment
+ * [...original code...]
*/
static void
pstip_transform_inst(struct tgsi_transform_context *ctx,
@@ -261,7 +272,7 @@ pstip_transform_inst(struct tgsi_transform_context *ctx,
uint i;
int wincoordInput;
- /* find free sampler */
+ /* find free texture sampler */
pctx->freeSampler = free_bit(pctx->samplersUsed);
if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
@@ -271,7 +282,7 @@ pstip_transform_inst(struct tgsi_transform_context *ctx,
else
wincoordInput = pctx->wincoordInput;
- /* find one free temp reg */
+ /* find one free temp register */
for (i = 0; i < 32; i++) {
if ((pctx->tempsUsed & (1 << i)) == 0) {
/* found a free temp */
@@ -397,6 +408,7 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe,
struct pipe_shader_state *new_fs;
struct pstip_transform_context transform;
const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS;
+ unsigned i;
new_fs = MALLOC(sizeof(*new_fs));
if (!new_fs)
@@ -408,22 +420,33 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe,
return NULL;
}
+ /* Setup shader transformation info/context.
+ */
memset(&transform, 0, sizeof(transform));
transform.wincoordInput = -1;
transform.maxInput = -1;
transform.texTemp = -1;
transform.firstInstruction = TRUE;
+ transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT;
transform.base.transform_instruction = pstip_transform_inst;
transform.base.transform_declaration = pstip_transform_decl;
transform.base.transform_immediate = pstip_transform_immed;
+ tgsi_scan_shader(fs->tokens, &transform.info);
+
+ /* find fragment coordinate origin property */
+ for (i = 0; i < transform.info.num_properties; i++) {
+ if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN)
+ transform.coordOrigin = transform.info.properties[i].data[0];
+ }
+
tgsi_transform_shader(fs->tokens,
(struct tgsi_token *) new_fs->tokens,
newLen, &transform.base);
#if 0 /* DEBUG */
tgsi_dump(fs->tokens, 0);
- tgsi_dump(pstip_fs.tokens, 0);
+ tgsi_dump(new_fs->tokens, 0);
#endif
assert(transform.freeSampler < PIPE_MAX_SAMPLERS);
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c
index 374fc336b83..d9b39e528bb 100644
--- a/src/gallium/auxiliary/util/u_vbuf_mgr.c
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c
@@ -34,21 +34,6 @@
#include "translate/translate.h"
#include "translate/translate_cache.h"
-/* Hardware vertex fetcher limitations can be described by this structure. */
-struct u_vbuf_caps {
- /* Vertex format CAPs. */
- /* TRUE if hardware supports it. */
- unsigned format_fixed32:1; /* PIPE_FORMAT_*32*_FIXED */
- unsigned format_float16:1; /* PIPE_FORMAT_*16*_FLOAT */
- unsigned format_float64:1; /* PIPE_FORMAT_*64*_FLOAT */
- unsigned format_norm32:1; /* PIPE_FORMAT_*32*NORM */
- unsigned format_scaled32:1; /* PIPE_FORMAT_*32*SCALED */
-
- /* Whether vertex fetches don't have to be dword-aligned. */
- /* TRUE if hardware supports it. */
- unsigned fetch_dword_unaligned:1;
-};
-
struct u_vbuf_mgr_elements {
unsigned count;
struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
@@ -69,7 +54,6 @@ struct u_vbuf_mgr_elements {
struct u_vbuf_mgr_priv {
struct u_vbuf_mgr b;
- struct u_vbuf_caps caps;
struct pipe_context *pipe;
struct translate_cache *translate_cache;
@@ -79,6 +63,8 @@ struct u_vbuf_mgr_priv {
void *saved_ve, *fallback_ve;
boolean ve_binding_lock;
+ unsigned saved_buffer_offset[PIPE_MAX_ATTRIBS];
+
boolean any_user_vbs;
boolean incompatible_vb_layout;
};
@@ -87,25 +73,25 @@ static void u_vbuf_mgr_init_format_caps(struct u_vbuf_mgr_priv *mgr)
{
struct pipe_screen *screen = mgr->pipe->screen;
- mgr->caps.format_fixed32 =
+ mgr->b.caps.format_fixed32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
- mgr->caps.format_float16 =
+ mgr->b.caps.format_float16 =
screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
- mgr->caps.format_float64 =
+ mgr->b.caps.format_float64 =
screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
- mgr->caps.format_norm32 =
+ mgr->b.caps.format_norm32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER) &&
screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
- mgr->caps.format_scaled32 =
+ mgr->b.caps.format_scaled32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER) &&
screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER,
@@ -128,7 +114,7 @@ u_vbuf_mgr_create(struct pipe_context *pipe,
upload_buffer_alignment,
upload_buffer_bind);
- mgr->caps.fetch_dword_unaligned =
+ mgr->b.caps.fetch_dword_unaligned =
fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED;
u_vbuf_mgr_init_format_caps(mgr);
@@ -182,7 +168,7 @@ u_vbuf_translate_begin(struct u_vbuf_mgr_priv *mgr,
/* Check for support. */
if (mgr->ve->ve[i].src_format == mgr->ve->native_format[i] &&
- (mgr->caps.fetch_dword_unaligned ||
+ (mgr->b.caps.fetch_dword_unaligned ||
(vb->buffer_offset % 4 == 0 &&
vb->stride % 4 == 0 &&
mgr->ve->ve[i].src_offset % 4 == 0))) {
@@ -363,7 +349,7 @@ u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
/* Choose a native format.
* For now we don't care about the alignment, that's going to
* be sorted out later. */
- if (!mgr->caps.format_fixed32) {
+ if (!mgr->b.caps.format_fixed32) {
switch (format) {
FORMAT_REPLACE(R32_FIXED, R32_FLOAT);
FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT);
@@ -372,7 +358,7 @@ u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
default:;
}
}
- if (!mgr->caps.format_float16) {
+ if (!mgr->b.caps.format_float16) {
switch (format) {
FORMAT_REPLACE(R16_FLOAT, R32_FLOAT);
FORMAT_REPLACE(R16G16_FLOAT, R32G32_FLOAT);
@@ -381,7 +367,7 @@ u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
default:;
}
}
- if (!mgr->caps.format_float64) {
+ if (!mgr->b.caps.format_float64) {
switch (format) {
FORMAT_REPLACE(R64_FLOAT, R32_FLOAT);
FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT);
@@ -390,7 +376,7 @@ u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
default:;
}
}
- if (!mgr->caps.format_norm32) {
+ if (!mgr->b.caps.format_norm32) {
switch (format) {
FORMAT_REPLACE(R32_UNORM, R32_FLOAT);
FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT);
@@ -403,7 +389,7 @@ u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
default:;
}
}
- if (!mgr->caps.format_scaled32) {
+ if (!mgr->b.caps.format_scaled32) {
switch (format) {
FORMAT_REPLACE(R32_USCALED, R32_FLOAT);
FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT);
@@ -425,11 +411,11 @@ u_vbuf_mgr_create_vertex_elements(struct u_vbuf_mgr *mgrb,
ve->incompatible_layout =
ve->incompatible_layout ||
ve->ve[i].src_format != ve->native_format[i] ||
- (!mgr->caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0);
+ (!mgr->b.caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0);
}
/* Align the formats to the size of DWORD if needed. */
- if (!mgr->caps.fetch_dword_unaligned) {
+ if (!mgr->b.caps.fetch_dword_unaligned) {
for (i = 0; i < count; i++) {
ve->native_format_size[i] = align(ve->native_format_size[i], 4);
}
@@ -470,7 +456,7 @@ void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb,
mgr->any_user_vbs = FALSE;
mgr->incompatible_vb_layout = FALSE;
- if (!mgr->caps.fetch_dword_unaligned) {
+ if (!mgr->b.caps.fetch_dword_unaligned) {
/* Check if the strides and offsets are aligned to the size of DWORD. */
for (i = 0; i < count; i++) {
if (bufs[i].buffer) {
@@ -488,6 +474,7 @@ void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb,
pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer);
pipe_resource_reference(&mgr->b.real_vertex_buffer[i], NULL);
+ mgr->saved_buffer_offset[i] = vb->buffer_offset;
if (!vb->buffer) {
continue;
@@ -647,6 +634,13 @@ u_vbuf_mgr_draw_begin(struct u_vbuf_mgr *mgrb,
void u_vbuf_mgr_draw_end(struct u_vbuf_mgr *mgrb)
{
struct u_vbuf_mgr_priv *mgr = (struct u_vbuf_mgr_priv*)mgrb;
+ unsigned i;
+
+ /* buffer offsets were modified in u_vbuf_upload_buffers */
+ if (mgr->any_user_vbs) {
+ for (i = 0; i < mgr->b.nr_vertex_buffers; i++)
+ mgr->b.vertex_buffer[i].buffer_offset = mgr->saved_buffer_offset[i];
+ }
if (mgr->fallback_ve) {
u_vbuf_translate_end(mgr);
diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.h b/src/gallium/auxiliary/util/u_vbuf_mgr.h
index 4e6372435d8..c653ca4346d 100644
--- a/src/gallium/auxiliary/util/u_vbuf_mgr.h
+++ b/src/gallium/auxiliary/util/u_vbuf_mgr.h
@@ -37,6 +37,21 @@
#include "pipe/p_state.h"
#include "util/u_transfer.h"
+/* Hardware vertex fetcher limitations can be described by this structure. */
+struct u_vbuf_caps {
+ /* Vertex format CAPs. */
+ /* TRUE if hardware supports it. */
+ unsigned format_fixed32:1; /* PIPE_FORMAT_*32*_FIXED */
+ unsigned format_float16:1; /* PIPE_FORMAT_*16*_FLOAT */
+ unsigned format_float64:1; /* PIPE_FORMAT_*64*_FLOAT */
+ unsigned format_norm32:1; /* PIPE_FORMAT_*32*NORM */
+ unsigned format_scaled32:1; /* PIPE_FORMAT_*32*SCALED */
+
+ /* Whether vertex fetches don't have to be dword-aligned. */
+ /* TRUE if hardware supports it. */
+ unsigned fetch_dword_unaligned:1;
+};
+
/* The manager.
* This structure should also be used to access vertex buffers
* from a driver. */
@@ -63,6 +78,8 @@ struct u_vbuf_mgr {
* - u_upload_buffer
* - u_upload_flush */
struct u_upload_mgr *uploader;
+
+ struct u_vbuf_caps caps;
};
struct u_vbuf_resource {
diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c
index 3bd4af2e3e0..c73f9769446 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.c
+++ b/src/gallium/auxiliary/vl/vl_compositor.c
@@ -231,6 +231,8 @@ init_pipe_state(struct vl_compositor *c)
struct pipe_rasterizer_state rast;
struct pipe_sampler_state sampler;
struct pipe_blend_state blend;
+ struct pipe_depth_stencil_alpha_state dsa;
+ unsigned i;
assert(c);
@@ -289,6 +291,24 @@ init_pipe_state(struct vl_compositor *c)
c->rast = c->pipe->create_rasterizer_state(c->pipe, &rast);
+ memset(&dsa, 0, sizeof dsa);
+ dsa.depth.enabled = 0;
+ dsa.depth.writemask = 0;
+ dsa.depth.func = PIPE_FUNC_ALWAYS;
+ for (i = 0; i < 2; ++i) {
+ dsa.stencil[i].enabled = 0;
+ dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
+ dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa.stencil[i].valuemask = 0;
+ dsa.stencil[i].writemask = 0;
+ }
+ dsa.alpha.enabled = 0;
+ dsa.alpha.func = PIPE_FUNC_ALWAYS;
+ dsa.alpha.ref_value = 0;
+ c->dsa = c->pipe->create_depth_stencil_alpha_state(c->pipe, &dsa);
+ c->pipe->bind_depth_stencil_alpha_state(c->pipe, c->dsa);
return true;
}
@@ -296,6 +316,11 @@ static void cleanup_pipe_state(struct vl_compositor *c)
{
assert(c);
+ /* Asserted in softpipe_delete_fs_state() for some reason */
+ c->pipe->bind_vs_state(c->pipe, NULL);
+ c->pipe->bind_fs_state(c->pipe, NULL);
+
+ c->pipe->delete_depth_stencil_alpha_state(c->pipe, c->dsa);
c->pipe->delete_sampler_state(c->pipe, c->sampler_linear);
c->pipe->delete_sampler_state(c->pipe, c->sampler_nearest);
c->pipe->delete_blend_state(c->pipe, c->blend);
@@ -648,7 +673,6 @@ vl_compositor_set_rgba_layer(struct vl_compositor *c,
void
vl_compositor_render(struct vl_compositor *c,
- enum pipe_mpeg12_picture_type picture_type,
struct pipe_surface *dst_surface,
struct pipe_video_rect *dst_area,
struct pipe_video_rect *dst_clip)
diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h
index 87ad39be1be..207510092a0 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.h
+++ b/src/gallium/auxiliary/vl/vl_compositor.h
@@ -68,6 +68,7 @@ struct vl_compositor
void *sampler_nearest;
void *blend;
void *rast;
+ void *dsa;
void *vertex_elems_state;
void *vs;
@@ -155,7 +156,6 @@ vl_compositor_set_rgba_layer(struct vl_compositor *compositor,
*/
void
vl_compositor_render(struct vl_compositor *compositor,
- enum pipe_mpeg12_picture_type picture_type,
struct pipe_surface *dst_surface,
struct pipe_video_rect *dst_area,
struct pipe_video_rect *dst_clip);
diff --git a/src/gallium/auxiliary/vl/vl_decoder.c b/src/gallium/auxiliary/vl/vl_decoder.c
index fac03359a0f..b23827d300a 100644
--- a/src/gallium/auxiliary/vl/vl_decoder.c
+++ b/src/gallium/auxiliary/vl/vl_decoder.c
@@ -44,6 +44,19 @@ vl_profile_supported(struct pipe_screen *screen, enum pipe_video_profile profile
}
}
+unsigned
+vl_num_buffers_desired(struct pipe_screen *screen, enum pipe_video_profile profile)
+{
+ assert(screen);
+ switch (u_reduce_video_profile(profile)) {
+ case PIPE_VIDEO_CODEC_MPEG12:
+ return 4;
+
+ default:
+ return 1;
+ }
+}
+
struct pipe_video_decoder *
vl_create_decoder(struct pipe_context *pipe,
enum pipe_video_profile profile,
diff --git a/src/gallium/auxiliary/vl/vl_decoder.h b/src/gallium/auxiliary/vl/vl_decoder.h
index 0e9280dbfa2..fed529c9bc7 100644
--- a/src/gallium/auxiliary/vl/vl_decoder.h
+++ b/src/gallium/auxiliary/vl/vl_decoder.h
@@ -38,6 +38,12 @@ bool
vl_profile_supported(struct pipe_screen *screen, enum pipe_video_profile profile);
/**
+ * the desired number of buffers for optimal operation
+ */
+unsigned
+vl_num_buffers_desired(struct pipe_screen *screen, enum pipe_video_profile profile);
+
+/**
* standard implementation of pipe->create_video_decoder
*/
struct pipe_video_decoder *
diff --git a/src/gallium/auxiliary/vl/vl_idct.c b/src/gallium/auxiliary/vl/vl_idct.c
index 645d06a0925..ad786145392 100644
--- a/src/gallium/auxiliary/vl/vl_idct.c
+++ b/src/gallium/auxiliary/vl/vl_idct.c
@@ -143,7 +143,7 @@ static void *
create_mismatch_vert_shader(struct vl_idct *idct)
{
struct ureg_program *shader;
- struct ureg_src vrect, vpos;
+ struct ureg_src vpos;
struct ureg_src scale;
struct ureg_dst t_tex;
struct ureg_dst o_vpos, o_addr[2];
@@ -152,7 +152,6 @@ create_mismatch_vert_shader(struct vl_idct *idct)
if (!shader)
return NULL;
- vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
t_tex = ureg_DECL_temporary(shader);
diff --git a/src/gallium/auxiliary/vl/vl_mc.c b/src/gallium/auxiliary/vl/vl_mc.c
index bd05205b52d..0b3723c9792 100644
--- a/src/gallium/auxiliary/vl/vl_mc.c
+++ b/src/gallium/auxiliary/vl/vl_mc.c
@@ -103,16 +103,15 @@ create_ref_vert_shader(struct vl_mc *r)
{
struct ureg_program *shader;
struct ureg_src mv_scale;
- struct ureg_src vrect, vmv[2];
+ struct ureg_src vmv[2];
struct ureg_dst t_vpos;
- struct ureg_dst o_vpos, o_vmv[2];
+ struct ureg_dst o_vmv[2];
unsigned i;
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
- vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
vmv[0] = ureg_DECL_vs_input(shader, VS_I_MV_TOP);
vmv[1] = ureg_DECL_vs_input(shader, VS_I_MV_BOTTOM);
@@ -121,7 +120,6 @@ create_ref_vert_shader(struct vl_mc *r)
(float)MACROBLOCK_HEIGHT / r->buffer_height)
);
- o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
o_vmv[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP);
o_vmv[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM);
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
index 9dd032e911d..db05b151f95 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
@@ -1,6 +1,7 @@
/**************************************************************************
*
- * Copyright 2011 Christian König.
+ * Copyright 2011 Maarten Lankhorst
+ * Copyright 2011 Christian König
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,1813 +26,967 @@
*
**************************************************************************/
-/**
- * This file is based uppon slice_xvmc.c and vlc.h from the xine project,
- * which in turn is based on mpeg2dec. The following is the original copyright:
- *
- * Copyright (C) 2000-2002 Michel Lespinasse <[email protected]>
- * Copyright (C) 1999-2000 Aaron Holtzman <[email protected]>
- *
- * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
- * See http://libmpeg2.sourceforge.net/ for updates.
- *
- * mpeg2dec 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 2 of the License, or
- * (at your option) any later version.
- *
- * mpeg2dec 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdint.h>
-
-#include <pipe/p_compiler.h>
-#include <pipe/p_video_state.h>
+#include <pipe/p_video_decoder.h>
+#include <util/u_memory.h>
#include "vl_vlc.h"
#include "vl_mpeg12_bitstream.h"
-/* take num bits from the high part of bit_buf and zero extend them */
-#define UBITS(buf,num) (((uint32_t)(buf)) >> (32 - (num)))
-
-/* take num bits from the high part of bit_buf and sign extend them */
-#define SBITS(buf,num) (((int32_t)(buf)) >> (32 - (num)))
-
-/* macroblock modes */
-#define MACROBLOCK_INTRA 1
-#define MACROBLOCK_PATTERN 2
-#define MACROBLOCK_MOTION_BACKWARD 4
-#define MACROBLOCK_MOTION_FORWARD 8
-#define MACROBLOCK_QUANT 16
-
-/* motion_type */
-#define MOTION_TYPE_MASK (3*64)
-#define MOTION_TYPE_BASE 64
-#define MC_FIELD (1*64)
-#define MC_FRAME (2*64)
-#define MC_16X8 (2*64)
-#define MC_DMV (3*64)
-
-/* picture structure */
-#define TOP_FIELD 1
-#define BOTTOM_FIELD 2
-#define FRAME_PICTURE 3
-
-/* picture coding type (mpeg2 header) */
-#define I_TYPE 1
-#define P_TYPE 2
-#define B_TYPE 3
-#define D_TYPE 4
-
-typedef struct {
- uint8_t modes;
- uint8_t len;
-} MBtab;
-
-typedef struct {
- uint8_t delta;
- uint8_t len;
-} MVtab;
-
-typedef struct {
- int8_t dmv;
- uint8_t len;
-} DMVtab;
-
-typedef struct {
- uint8_t cbp;
- uint8_t len;
-} CBPtab;
-
-typedef struct {
- uint8_t size;
- uint8_t len;
-} DCtab;
-
-typedef struct {
- uint8_t run;
- uint8_t level;
- uint8_t len;
-} DCTtab;
-
-typedef struct {
- uint8_t mba;
- uint8_t len;
-} MBAtab;
-
-#define INTRA MACROBLOCK_INTRA
-#define QUANT MACROBLOCK_QUANT
-#define MC MACROBLOCK_MOTION_FORWARD
-#define CODED MACROBLOCK_PATTERN
-#define FWD MACROBLOCK_MOTION_FORWARD
-#define BWD MACROBLOCK_MOTION_BACKWARD
-#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD
-
-static const MBtab MB_I [] = {
- {INTRA|QUANT, 2}, {INTRA, 1}
-};
-
-static const MBtab MB_P [] = {
- {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5},
- {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3},
- {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
- {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2},
- {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
- {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
- {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1},
- {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}
-};
-
-static const MBtab MB_B [] = {
- {0, 0}, {INTRA|QUANT, 6},
- {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6},
- {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5},
- {INTRA, 5}, {INTRA, 5},
- {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4},
- {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4},
- {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
- {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3},
- {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
- {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3},
- {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
- {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
- {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
- {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2},
- {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
- {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
- {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
- {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}
-};
-
-#undef INTRA
-#undef QUANT
-#undef MC
-#undef CODED
-#undef FWD
-#undef BWD
-#undef INTER
-
-static const MVtab MV_4 [] = {
- { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
-};
-
-static const MVtab MV_10 [] = {
- { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10},
- { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10},
- {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9},
- { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7},
- { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7},
- { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}
-};
-
-static const DMVtab DMV_2 [] = {
- { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
-};
-
-static const CBPtab CBP_7 [] = {
- {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7},
- {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7},
- {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6},
- {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6},
- {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5},
- {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5},
- {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5},
- {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5},
- {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5},
- {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5},
- {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5},
- {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5},
- {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5},
- {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5},
- {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5},
- {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5},
- {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
- {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
- {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
- {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
- {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
- {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
- {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
- {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
- {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
- {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
- {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
- {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}
-};
-
-static const CBPtab CBP_9 [] = {
- {0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9},
- {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9},
- {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8},
- {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8},
- {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8},
- {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8},
- {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8},
- {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8},
- {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8},
- {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8},
- {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8},
- {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8},
- {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8},
- {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8},
- {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8},
- {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8}
+enum {
+ dct_End_of_Block = 0xFF,
+ dct_Escape = 0xFE,
+ dct_DC = 0xFD,
+ dct_AC = 0xFC
};
-static const DCtab DC_lum_5 [] = {
- {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
- {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
- {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
- {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}
+struct dct_coeff
+{
+ uint8_t length;
+ uint8_t run;
+ int16_t level;
};
-static const DCtab DC_chrom_5 [] = {
- {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
- {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
- {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
- {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}
+struct dct_coeff_compressed
+{
+ uint32_t bitcode;
+ struct dct_coeff coeff;
};
-static const DCtab DC_long [] = {
- {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
- {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
- {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6},
- {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
+/* coding table as found in the spec annex B.5 table B-1 */
+static const struct vl_vlc_compressed macroblock_address_increment[] = {
+ { 0x8000, { 1, 1 } },
+ { 0x6000, { 3, 2 } },
+ { 0x4000, { 3, 3 } },
+ { 0x3000, { 4, 4 } },
+ { 0x2000, { 4, 5 } },
+ { 0x1800, { 5, 6 } },
+ { 0x1000, { 5, 7 } },
+ { 0x0e00, { 7, 8 } },
+ { 0x0c00, { 7, 9 } },
+ { 0x0b00, { 8, 10 } },
+ { 0x0a00, { 8, 11 } },
+ { 0x0900, { 8, 12 } },
+ { 0x0800, { 8, 13 } },
+ { 0x0700, { 8, 14 } },
+ { 0x0600, { 8, 15 } },
+ { 0x05c0, { 10, 16 } },
+ { 0x0580, { 10, 17 } },
+ { 0x0540, { 10, 18 } },
+ { 0x0500, { 10, 19 } },
+ { 0x04c0, { 10, 20 } },
+ { 0x0480, { 10, 21 } },
+ { 0x0460, { 11, 22 } },
+ { 0x0440, { 11, 23 } },
+ { 0x0420, { 11, 24 } },
+ { 0x0400, { 11, 25 } },
+ { 0x03e0, { 11, 26 } },
+ { 0x03c0, { 11, 27 } },
+ { 0x03a0, { 11, 28 } },
+ { 0x0380, { 11, 29 } },
+ { 0x0360, { 11, 30 } },
+ { 0x0340, { 11, 31 } },
+ { 0x0320, { 11, 32 } },
+ { 0x0300, { 11, 33 } }
};
-static const DCTtab DCT_16 [] = {
- {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
- {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
- {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
- {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
- { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0},
- { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0},
- { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0},
- { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0}
-};
+#define Q PIPE_MPEG12_MB_TYPE_QUANT
+#define F PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
+#define B PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
+#define P PIPE_MPEG12_MB_TYPE_PATTERN
+#define I PIPE_MPEG12_MB_TYPE_INTRA
-static const DCTtab DCT_15 [] = {
- { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15},
- { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15},
- { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15},
- { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15},
- { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14},
- { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14},
- { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14},
- { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14},
- { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14},
- { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14},
- { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14},
- { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14}
+/* coding table as found in the spec annex B.5 table B-2 */
+static const struct vl_vlc_compressed macroblock_type_i[] = {
+ { 0x8000, { 1, I } },
+ { 0x4000, { 2, Q|I } }
};
-static const DCTtab DCT_13 [] = {
- { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13},
- { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13},
- { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13},
- { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13},
- { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12},
- { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12},
- { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12},
- { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12},
- { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12},
- { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12},
- { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12},
- { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12}
+/* coding table as found in the spec annex B.5 table B-3 */
+static const struct vl_vlc_compressed macroblock_type_p[] = {
+ { 0x8000, { 1, F|P } },
+ { 0x4000, { 2, P } },
+ { 0x2000, { 3, F } },
+ { 0x1800, { 5, I } },
+ { 0x1000, { 5, Q|F|P } },
+ { 0x0800, { 5, Q|P } },
+ { 0x0400, { 6, Q|I } }
};
-static const DCTtab DCT_B14_10 [] = {
- { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10},
- { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10}
+/* coding table as found in the spec annex B.5 table B-4 */
+static const struct vl_vlc_compressed macroblock_type_b[] = {
+ { 0x8000, { 2, F|B } },
+ { 0xC000, { 2, F|B|P } },
+ { 0x4000, { 3, B } },
+ { 0x6000, { 3, B|P } },
+ { 0x2000, { 4, F } },
+ { 0x3000, { 4, F|P } },
+ { 0x1800, { 5, I } },
+ { 0x1000, { 5, Q|F|B|P } },
+ { 0x0C00, { 6, Q|F|P } },
+ { 0x0800, { 6, Q|B|P } },
+ { 0x0400, { 6, Q|I } }
};
-static const DCTtab DCT_B14_8 [] = {
- { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
- { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7},
- { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7},
- { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6},
- { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6},
- { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6},
- { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
- { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8},
- { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8}
+#undef Q
+#undef F
+#undef B
+#undef P
+#undef I
+
+/* coding table as found in the spec annex B.5 table B-9 */
+static const struct vl_vlc_compressed coded_block_pattern[] = {
+ { 0xE000, { 3, 60 } },
+ { 0xD000, { 4, 4 } },
+ { 0xC000, { 4, 8 } },
+ { 0xB000, { 4, 16 } },
+ { 0xA000, { 4, 32 } },
+ { 0x9800, { 5, 12 } },
+ { 0x9000, { 5, 48 } },
+ { 0x8800, { 5, 20 } },
+ { 0x8000, { 5, 40 } },
+ { 0x7800, { 5, 28 } },
+ { 0x7000, { 5, 44 } },
+ { 0x6800, { 5, 52 } },
+ { 0x6000, { 5, 56 } },
+ { 0x5800, { 5, 1 } },
+ { 0x5000, { 5, 61 } },
+ { 0x4800, { 5, 2 } },
+ { 0x4000, { 5, 62 } },
+ { 0x3C00, { 6, 24 } },
+ { 0x3800, { 6, 36 } },
+ { 0x3400, { 6, 3 } },
+ { 0x3000, { 6, 63 } },
+ { 0x2E00, { 7, 5 } },
+ { 0x2C00, { 7, 9 } },
+ { 0x2A00, { 7, 17 } },
+ { 0x2800, { 7, 33 } },
+ { 0x2600, { 7, 6 } },
+ { 0x2400, { 7, 10 } },
+ { 0x2200, { 7, 18 } },
+ { 0x2000, { 7, 34 } },
+ { 0x1F00, { 8, 7 } },
+ { 0x1E00, { 8, 11 } },
+ { 0x1D00, { 8, 19 } },
+ { 0x1C00, { 8, 35 } },
+ { 0x1B00, { 8, 13 } },
+ { 0x1A00, { 8, 49 } },
+ { 0x1900, { 8, 21 } },
+ { 0x1800, { 8, 41 } },
+ { 0x1700, { 8, 14 } },
+ { 0x1600, { 8, 50 } },
+ { 0x1500, { 8, 22 } },
+ { 0x1400, { 8, 42 } },
+ { 0x1300, { 8, 15 } },
+ { 0x1200, { 8, 51 } },
+ { 0x1100, { 8, 23 } },
+ { 0x1000, { 8, 43 } },
+ { 0x0F00, { 8, 25 } },
+ { 0x0E00, { 8, 37 } },
+ { 0x0D00, { 8, 26 } },
+ { 0x0C00, { 8, 38 } },
+ { 0x0B00, { 8, 29 } },
+ { 0x0A00, { 8, 45 } },
+ { 0x0900, { 8, 53 } },
+ { 0x0800, { 8, 57 } },
+ { 0x0700, { 8, 30 } },
+ { 0x0600, { 8, 46 } },
+ { 0x0500, { 8, 54 } },
+ { 0x0400, { 8, 58 } },
+ { 0x0380, { 9, 31 } },
+ { 0x0300, { 9, 47 } },
+ { 0x0280, { 9, 55 } },
+ { 0x0200, { 9, 59 } },
+ { 0x0180, { 9, 27 } },
+ { 0x0100, { 9, 39 } },
+ { 0x0080, { 9, 0 } }
};
-static const DCTtab DCT_B14AC_5 [] = {
- { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
- { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
- {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}
+/* coding table as found in the spec annex B.5 table B-10 */
+static const struct vl_vlc_compressed motion_code[] = {
+ { 0x0320, { 11, -16 } },
+ { 0x0360, { 11, -15 } },
+ { 0x03a0, { 11, -14 } },
+ { 0x03e0, { 11, -13 } },
+ { 0x0420, { 11, -12 } },
+ { 0x0460, { 11, -11 } },
+ { 0x04c0, { 10, -10 } },
+ { 0x0540, { 10, -9 } },
+ { 0x05c0, { 10, -8 } },
+ { 0x0700, { 8, -7 } },
+ { 0x0900, { 8, -6 } },
+ { 0x0b00, { 8, -5 } },
+ { 0x0e00, { 7, -4 } },
+ { 0x1800, { 5, -3 } },
+ { 0x3000, { 4, -2 } },
+ { 0x6000, { 3, -1 } },
+ { 0x8000, { 1, 0 } },
+ { 0x4000, { 3, 1 } },
+ { 0x2000, { 4, 2 } },
+ { 0x1000, { 5, 3 } },
+ { 0x0c00, { 7, 4 } },
+ { 0x0a00, { 8, 5 } },
+ { 0x0800, { 8, 6 } },
+ { 0x0600, { 8, 7 } },
+ { 0x0580, { 10, 8 } },
+ { 0x0500, { 10, 9 } },
+ { 0x0480, { 10, 10 } },
+ { 0x0440, { 11, 11 } },
+ { 0x0400, { 11, 12 } },
+ { 0x03c0, { 11, 13 } },
+ { 0x0380, { 11, 14 } },
+ { 0x0340, { 11, 15 } },
+ { 0x0300, { 11, 16 } }
};
-static const DCTtab DCT_B14DC_5 [] = {
- { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5},
- { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
- { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
- { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1},
- { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}
+/* coding table as found in the spec annex B.5 table B-11 */
+static const struct vl_vlc_compressed dmvector[] = {
+ { 0x0000, { 1, 0 } },
+ { 0x8000, { 2, 1 } },
+ { 0xc000, { 2, -1 } }
};
-static const DCTtab DCT_B15_10 [] = {
- { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9},
- { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9}
+/* coding table as found in the spec annex B.5 table B-12 */
+static const struct vl_vlc_compressed dct_dc_size_luminance[] = {
+ { 0x8000, { 3, 0 } },
+ { 0x0000, { 2, 1 } },
+ { 0x4000, { 2, 2 } },
+ { 0xA000, { 3, 3 } },
+ { 0xC000, { 3, 4 } },
+ { 0xE000, { 4, 5 } },
+ { 0xF000, { 5, 6 } },
+ { 0xF800, { 6, 7 } },
+ { 0xFC00, { 7, 8 } },
+ { 0xFE00, { 8, 9 } },
+ { 0xFF00, { 9, 10 } },
+ { 0xFF80, { 9, 11 } }
};
-static const DCTtab DCT_B15_8 [] = {
- { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
- { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7},
- { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7},
- { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6},
- { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6},
- { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6},
- { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6},
- { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8},
- { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8},
- { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
- { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5},
- { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
- { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5},
- { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
- { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3},
- {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
- {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
- {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
- {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
- { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
- { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
- { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
- { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3},
- { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
- { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5},
- { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
- { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5},
- { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7},
- { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7},
- { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8},
- { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8}
+/* coding table as found in the spec annex B.5 table B-13 */
+static const struct vl_vlc_compressed dct_dc_size_chrominance[] = {
+ { 0x0000, { 2, 0 } },
+ { 0x4000, { 2, 1 } },
+ { 0x8000, { 2, 2 } },
+ { 0xC000, { 3, 3 } },
+ { 0xE000, { 4, 4 } },
+ { 0xF000, { 5, 5 } },
+ { 0xF800, { 6, 6 } },
+ { 0xFC00, { 7, 7 } },
+ { 0xFE00, { 8, 8 } },
+ { 0xFF00, { 9, 9 } },
+ { 0xFF80, { 10, 10 } },
+ { 0xFFC0, { 10, 11 } }
};
-static const MBAtab MBA_5 [] = {
- {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4},
- {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
- {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
- {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}
+/* coding table as found in the spec annex B.5 table B-14 */
+static const struct dct_coeff_compressed dct_coeff_tbl_zero[] = {
+ { 0x8000, { 2, dct_End_of_Block, 0 } },
+ { 0x8000, { 1, dct_DC, 1 } },
+ { 0xC000, { 2, dct_AC, 1 } },
+ { 0x6000, { 3, 1, 1 } },
+ { 0x4000, { 4, 0, 2 } },
+ { 0x5000, { 4, 2, 1 } },
+ { 0x2800, { 5, 0, 3 } },
+ { 0x3800, { 5, 3, 1 } },
+ { 0x3000, { 5, 4, 1 } },
+ { 0x1800, { 6, 1, 2 } },
+ { 0x1C00, { 6, 5, 1 } },
+ { 0x1400, { 6, 6, 1 } },
+ { 0x1000, { 6, 7, 1 } },
+ { 0x0C00, { 7, 0, 4 } },
+ { 0x0800, { 7, 2, 2 } },
+ { 0x0E00, { 7, 8, 1 } },
+ { 0x0A00, { 7, 9, 1 } },
+ { 0x0400, { 6, dct_Escape, 0 } },
+ { 0x2600, { 8, 0, 5 } },
+ { 0x2100, { 8, 0, 6 } },
+ { 0x2500, { 8, 1, 3 } },
+ { 0x2400, { 8, 3, 2 } },
+ { 0x2700, { 8, 10, 1 } },
+ { 0x2300, { 8, 11, 1 } },
+ { 0x2200, { 8, 12, 1 } },
+ { 0x2000, { 8, 13, 1 } },
+ { 0x0280, { 10, 0, 7 } },
+ { 0x0300, { 10, 1, 4 } },
+ { 0x02C0, { 10, 2, 3 } },
+ { 0x03C0, { 10, 4, 2 } },
+ { 0x0240, { 10, 5, 2 } },
+ { 0x0380, { 10, 14, 1 } },
+ { 0x0340, { 10, 15, 1 } },
+ { 0x0200, { 10, 16, 1 } },
+ { 0x01D0, { 12, 0, 8 } },
+ { 0x0180, { 12, 0, 9 } },
+ { 0x0130, { 12, 0, 10 } },
+ { 0x0100, { 12, 0, 11 } },
+ { 0x01B0, { 12, 1, 5 } },
+ { 0x0140, { 12, 2, 4 } },
+ { 0x01C0, { 12, 3, 3 } },
+ { 0x0120, { 12, 4, 3 } },
+ { 0x01E0, { 12, 6, 2 } },
+ { 0x0150, { 12, 7, 2 } },
+ { 0x0110, { 12, 8, 2 } },
+ { 0x01F0, { 12, 17, 1 } },
+ { 0x01A0, { 12, 18, 1 } },
+ { 0x0190, { 12, 19, 1 } },
+ { 0x0170, { 12, 20, 1 } },
+ { 0x0160, { 12, 21, 1 } },
+ { 0x00D0, { 13, 0, 12 } },
+ { 0x00C8, { 13, 0, 13 } },
+ { 0x00C0, { 13, 0, 14 } },
+ { 0x00B8, { 13, 0, 15 } },
+ { 0x00B0, { 13, 1, 6 } },
+ { 0x00A8, { 13, 1, 7 } },
+ { 0x00A0, { 13, 2, 5 } },
+ { 0x0098, { 13, 3, 4 } },
+ { 0x0090, { 13, 5, 3 } },
+ { 0x0088, { 13, 9, 2 } },
+ { 0x0080, { 13, 10, 2 } },
+ { 0x00F8, { 13, 22, 1 } },
+ { 0x00F0, { 13, 23, 1 } },
+ { 0x00E8, { 13, 24, 1 } },
+ { 0x00E0, { 13, 25, 1 } },
+ { 0x00D8, { 13, 26, 1 } },
+ { 0x007C, { 14, 0, 16 } },
+ { 0x0078, { 14, 0, 17 } },
+ { 0x0074, { 14, 0, 18 } },
+ { 0x0070, { 14, 0, 19 } },
+ { 0x006C, { 14, 0, 20 } },
+ { 0x0068, { 14, 0, 21 } },
+ { 0x0064, { 14, 0, 22 } },
+ { 0x0060, { 14, 0, 23 } },
+ { 0x005C, { 14, 0, 24 } },
+ { 0x0058, { 14, 0, 25 } },
+ { 0x0054, { 14, 0, 26 } },
+ { 0x0050, { 14, 0, 27 } },
+ { 0x004C, { 14, 0, 28 } },
+ { 0x0048, { 14, 0, 29 } },
+ { 0x0044, { 14, 0, 30 } },
+ { 0x0040, { 14, 0, 31 } },
+ { 0x0030, { 15, 0, 32 } },
+ { 0x002E, { 15, 0, 33 } },
+ { 0x002C, { 15, 0, 34 } },
+ { 0x002A, { 15, 0, 35 } },
+ { 0x0028, { 15, 0, 36 } },
+ { 0x0026, { 15, 0, 37 } },
+ { 0x0024, { 15, 0, 38 } },
+ { 0x0022, { 15, 0, 39 } },
+ { 0x0020, { 15, 0, 40 } },
+ { 0x003E, { 15, 1, 8 } },
+ { 0x003C, { 15, 1, 9 } },
+ { 0x003A, { 15, 1, 10 } },
+ { 0x0038, { 15, 1, 11 } },
+ { 0x0036, { 15, 1, 12 } },
+ { 0x0034, { 15, 1, 13 } },
+ { 0x0032, { 15, 1, 14 } },
+ { 0x0013, { 16, 1, 15 } },
+ { 0x0012, { 16, 1, 16 } },
+ { 0x0011, { 16, 1, 17 } },
+ { 0x0010, { 16, 1, 18 } },
+ { 0x0014, { 16, 6, 3 } },
+ { 0x001A, { 16, 11, 2 } },
+ { 0x0019, { 16, 12, 2 } },
+ { 0x0018, { 16, 13, 2 } },
+ { 0x0017, { 16, 14, 2 } },
+ { 0x0016, { 16, 15, 2 } },
+ { 0x0015, { 16, 16, 2 } },
+ { 0x001F, { 16, 27, 1 } },
+ { 0x001E, { 16, 28, 1 } },
+ { 0x001D, { 16, 29, 1 } },
+ { 0x001C, { 16, 30, 1 } },
+ { 0x001B, { 16, 31, 1 } }
};
-static const MBAtab MBA_11 [] = {
- {32, 11}, {31, 11}, {30, 11}, {29, 11},
- {28, 11}, {27, 11}, {26, 11}, {25, 11},
- {24, 11}, {23, 11}, {22, 11}, {21, 11},
- {20, 10}, {20, 10}, {19, 10}, {19, 10},
- {18, 10}, {18, 10}, {17, 10}, {17, 10},
- {16, 10}, {16, 10}, {15, 10}, {15, 10},
- {14, 8}, {14, 8}, {14, 8}, {14, 8},
- {14, 8}, {14, 8}, {14, 8}, {14, 8},
- {13, 8}, {13, 8}, {13, 8}, {13, 8},
- {13, 8}, {13, 8}, {13, 8}, {13, 8},
- {12, 8}, {12, 8}, {12, 8}, {12, 8},
- {12, 8}, {12, 8}, {12, 8}, {12, 8},
- {11, 8}, {11, 8}, {11, 8}, {11, 8},
- {11, 8}, {11, 8}, {11, 8}, {11, 8},
- {10, 8}, {10, 8}, {10, 8}, {10, 8},
- {10, 8}, {10, 8}, {10, 8}, {10, 8},
- { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
- { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8},
- { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
- { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
- { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
- { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7},
- { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
- { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
- { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7},
- { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}
+/* coding table as found in the spec annex B.5 table B-15 */
+static const struct dct_coeff_compressed dct_coeff_tbl_one[] = {
+ { 0x6000, { 4, dct_End_of_Block, 0 } },
+ { 0x8000, { 2, 0, 1 } },
+ { 0x4000, { 3, 1, 1 } },
+ { 0xC000, { 3, 0, 2 } },
+ { 0x2800, { 5, 2, 1 } },
+ { 0x7000, { 4, 0, 3 } },
+ { 0x3800, { 5, 3, 1 } },
+ { 0x1800, { 6, 4, 1 } },
+ { 0x3000, { 5, 1, 2 } },
+ { 0x1C00, { 6, 5, 1 } },
+ { 0x0C00, { 7, 6, 1 } },
+ { 0x0800, { 7, 7, 1 } },
+ { 0xE000, { 5, 0, 4 } },
+ { 0x0E00, { 7, 2, 2 } },
+ { 0x0A00, { 7, 8, 1 } },
+ { 0xF000, { 7, 9, 1 } },
+ { 0x0400, { 6, dct_Escape, 0 } },
+ { 0xE800, { 5, 0, 5 } },
+ { 0x1400, { 6, 0, 6 } },
+ { 0xF200, { 7, 1, 3 } },
+ { 0x2600, { 8, 3, 2 } },
+ { 0xF400, { 7, 10, 1 } },
+ { 0x2100, { 8, 11, 1 } },
+ { 0x2500, { 8, 12, 1 } },
+ { 0x2400, { 8, 13, 1 } },
+ { 0x1000, { 6, 0, 7 } },
+ { 0x2700, { 8, 1, 4 } },
+ { 0xFC00, { 8, 2, 3 } },
+ { 0xFD00, { 8, 4, 2 } },
+ { 0x0200, { 9, 5, 2 } },
+ { 0x0280, { 9, 14, 1 } },
+ { 0x0380, { 9, 15, 1 } },
+ { 0x0340, { 10, 16, 1 } },
+ { 0xF600, { 7, 0, 8 } },
+ { 0xF800, { 7, 0, 9 } },
+ { 0x2300, { 8, 0, 10 } },
+ { 0x2200, { 8, 0, 11 } },
+ { 0x2000, { 8, 1, 5 } },
+ { 0x0300, { 10, 2, 4 } },
+ { 0x01C0, { 12, 3, 3 } },
+ { 0x0120, { 12, 4, 3 } },
+ { 0x01E0, { 12, 6, 2 } },
+ { 0x0150, { 12, 7, 2 } },
+ { 0x0110, { 12, 8, 2 } },
+ { 0x01F0, { 12, 17, 1 } },
+ { 0x01A0, { 12, 18, 1 } },
+ { 0x0190, { 12, 19, 1 } },
+ { 0x0170, { 12, 20, 1 } },
+ { 0x0160, { 12, 21, 1 } },
+ { 0xFA00, { 8, 0, 12 } },
+ { 0xFB00, { 8, 0, 13 } },
+ { 0xFE00, { 8, 0, 14 } },
+ { 0xFF00, { 8, 0, 15 } },
+ { 0x00B0, { 13, 1, 6 } },
+ { 0x00A8, { 13, 1, 7 } },
+ { 0x00A0, { 13, 2, 5 } },
+ { 0x0098, { 13, 3, 4 } },
+ { 0x0090, { 13, 5, 3 } },
+ { 0x0088, { 13, 9, 2 } },
+ { 0x0080, { 13, 10, 2 } },
+ { 0x00F8, { 13, 22, 1 } },
+ { 0x00F0, { 13, 23, 1 } },
+ { 0x00E8, { 13, 24, 1 } },
+ { 0x00E0, { 13, 25, 1 } },
+ { 0x00D8, { 13, 26, 1 } },
+ { 0x007C, { 14, 0, 16 } },
+ { 0x0078, { 14, 0, 17 } },
+ { 0x0074, { 14, 0, 18 } },
+ { 0x0070, { 14, 0, 19 } },
+ { 0x006C, { 14, 0, 20 } },
+ { 0x0068, { 14, 0, 21 } },
+ { 0x0064, { 14, 0, 22 } },
+ { 0x0060, { 14, 0, 23 } },
+ { 0x005C, { 14, 0, 24 } },
+ { 0x0058, { 14, 0, 25 } },
+ { 0x0054, { 14, 0, 26 } },
+ { 0x0050, { 14, 0, 27 } },
+ { 0x004C, { 14, 0, 28 } },
+ { 0x0048, { 14, 0, 29 } },
+ { 0x0044, { 14, 0, 30 } },
+ { 0x0040, { 14, 0, 31 } },
+ { 0x0030, { 15, 0, 32 } },
+ { 0x002E, { 15, 0, 33 } },
+ { 0x002C, { 15, 0, 34 } },
+ { 0x002A, { 15, 0, 35 } },
+ { 0x0028, { 15, 0, 36 } },
+ { 0x0026, { 15, 0, 37 } },
+ { 0x0024, { 15, 0, 38 } },
+ { 0x0022, { 15, 0, 39 } },
+ { 0x0020, { 15, 0, 40 } },
+ { 0x003E, { 15, 1, 8 } },
+ { 0x003C, { 15, 1, 9 } },
+ { 0x003A, { 15, 1, 10 } },
+ { 0x0038, { 15, 1, 11 } },
+ { 0x0036, { 15, 1, 12 } },
+ { 0x0034, { 15, 1, 13 } },
+ { 0x0032, { 15, 1, 14 } },
+ { 0x0013, { 16, 1, 15 } },
+ { 0x0012, { 16, 1, 16 } },
+ { 0x0011, { 16, 1, 17 } },
+ { 0x0010, { 16, 1, 18 } },
+ { 0x0014, { 16, 6, 3 } },
+ { 0x001A, { 16, 11, 2 } },
+ { 0x0019, { 16, 12, 2 } },
+ { 0x0018, { 16, 13, 2 } },
+ { 0x0017, { 16, 14, 2 } },
+ { 0x0016, { 16, 15, 2 } },
+ { 0x0015, { 16, 16, 2 } },
+ { 0x001F, { 16, 27, 1 } },
+ { 0x001E, { 16, 28, 1 } },
+ { 0x001D, { 16, 29, 1 } },
+ { 0x001C, { 16, 30, 1 } },
+ { 0x001B, { 16, 31, 1 } }
};
-static const int non_linear_quantizer_scale[] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 10, 12, 14, 16, 18, 20, 22,
- 24, 28, 32, 36, 40, 44, 48, 52,
- 56, 64, 72, 80, 88, 96, 104, 112
+/* q_scale_type */
+static const unsigned quant_scale[2][32] = {
+ { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 },
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24,
+ 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 }
};
-static INLINE int
-get_macroblock_modes(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture)
-{
- int macroblock_modes;
- const MBtab * tab;
-
- switch (picture->picture_coding_type) {
- case I_TYPE:
-
- tab = MB_I + vl_vlc_ubits(&bs->vlc, 1);
- vl_vlc_dumpbits(&bs->vlc, tab->len);
- macroblock_modes = tab->modes;
-
- return macroblock_modes;
-
- case P_TYPE:
-
- tab = MB_P + vl_vlc_ubits(&bs->vlc, 5);
- vl_vlc_dumpbits(&bs->vlc, tab->len);
- macroblock_modes = tab->modes;
-
- if (picture->picture_structure != FRAME_PICTURE) {
- if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) {
- macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
- vl_vlc_dumpbits(&bs->vlc, 2);
- }
- return macroblock_modes;
- } else if (picture->frame_pred_frame_dct) {
- if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
- macroblock_modes |= MC_FRAME;
- return macroblock_modes;
- } else {
- if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) {
- macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
- vl_vlc_dumpbits(&bs->vlc, 2);
- }
- return macroblock_modes;
- }
-
- case B_TYPE:
-
- tab = MB_B + vl_vlc_ubits(&bs->vlc, 6);
- vl_vlc_dumpbits(&bs->vlc, tab->len);
- macroblock_modes = tab->modes;
-
- if (picture->picture_structure != FRAME_PICTURE) {
- if (! (macroblock_modes & MACROBLOCK_INTRA)) {
- macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
- vl_vlc_dumpbits(&bs->vlc, 2);
- }
- } else if (picture->frame_pred_frame_dct) {
- macroblock_modes |= MC_FRAME;
- } else if (!(macroblock_modes & MACROBLOCK_INTRA)) {
- macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
- vl_vlc_dumpbits(&bs->vlc, 2);
- }
- return macroblock_modes;
-
- case D_TYPE:
+static struct vl_vlc_entry tbl_B1[1 << 11];
+static struct vl_vlc_entry tbl_B2[1 << 2];
+static struct vl_vlc_entry tbl_B3[1 << 6];
+static struct vl_vlc_entry tbl_B4[1 << 6];
+static struct vl_vlc_entry tbl_B9[1 << 9];
+static struct vl_vlc_entry tbl_B10[1 << 11];
+static struct vl_vlc_entry tbl_B11[1 << 2];
+static struct vl_vlc_entry tbl_B12[1 << 10];
+static struct vl_vlc_entry tbl_B13[1 << 10];
+static struct dct_coeff tbl_B14_DC[1 << 17];
+static struct dct_coeff tbl_B14_AC[1 << 17];
+static struct dct_coeff tbl_B15[1 << 17];
- vl_vlc_dumpbits(&bs->vlc, 1);
- return MACROBLOCK_INTRA;
-
- default:
- return 0;
- }
-}
-
-static INLINE enum pipe_mpeg12_dct_type
-get_dct_type(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture, int macroblock_modes)
+static INLINE void
+init_dct_coeff_table(struct dct_coeff *dst, const struct dct_coeff_compressed *src,
+ unsigned size, bool is_DC)
{
- enum pipe_mpeg12_dct_type dct_type = PIPE_MPEG12_DCT_TYPE_FRAME;
-
- if ((picture->picture_structure == FRAME_PICTURE) &&
- (!picture->frame_pred_frame_dct) &&
- (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))) {
+ unsigned i;
- dct_type = vl_vlc_ubits(&bs->vlc, 1) ? PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME;
- vl_vlc_dumpbits(&bs->vlc, 1);
+ for (i=0;i<(1<<17);++i) {
+ dst[i].length = 0;
+ dst[i].level = 0;
+ dst[i].run = dct_End_of_Block;
}
- return dct_type;
-}
-
-static INLINE int
-get_quantizer_scale(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture)
-{
- int quantizer_scale_code;
- quantizer_scale_code = vl_vlc_ubits(&bs->vlc, 5);
- vl_vlc_dumpbits(&bs->vlc, 5);
+ for(; size > 0; --size, ++src) {
+ struct dct_coeff coeff = src->coeff;
+ bool has_sign = true;
- if (picture->q_scale_type)
- return non_linear_quantizer_scale[quantizer_scale_code];
- else
- return quantizer_scale_code << 1;
-}
-
-static INLINE int
-get_motion_delta(struct vl_mpg12_bs *bs, unsigned f_code)
-{
- int delta;
- int sign;
- const MVtab * tab;
+ switch (coeff.run) {
+ case dct_End_of_Block:
+ if (is_DC)
+ continue;
- if (bs->vlc.buf & 0x80000000) {
- vl_vlc_dumpbits(&bs->vlc, 1);
- return 0;
- } else if (bs->vlc.buf >= 0x0c000000) {
+ has_sign = false;
+ break;
- tab = MV_4 + vl_vlc_ubits(&bs->vlc, 4);
- delta = (tab->delta << f_code) + 1;
- bs->vlc.bits += tab->len + f_code + 1;
- bs->vlc.buf <<= tab->len;
+ case dct_Escape:
+ has_sign = false;
+ break;
- sign = vl_vlc_sbits(&bs->vlc, 1);
- bs->vlc.buf <<= 1;
+ case dct_DC:
+ if (!is_DC)
+ continue;
- if (f_code)
- delta += vl_vlc_ubits(&bs->vlc, f_code);
- bs->vlc.buf <<= f_code;
+ coeff.length += 1;
+ coeff.run = 1;
+ break;
- return (delta ^ sign) - sign;
+ case dct_AC:
+ if (is_DC)
+ continue;
- } else {
+ coeff.length += 1;
+ coeff.run = 1;
+ break;
- tab = MV_10 + vl_vlc_ubits(&bs->vlc, 10);
- delta = (tab->delta << f_code) + 1;
- bs->vlc.bits += tab->len + 1;
- bs->vlc.buf <<= tab->len;
+ default:
+ coeff.length += 1;
+ coeff.run += 1;
+ break;
+ }
- sign = vl_vlc_sbits(&bs->vlc, 1);
- bs->vlc.buf <<= 1;
+ for(i=0; i<(1 << (17 - coeff.length)); ++i)
+ dst[src->bitcode << 1 | i] = coeff;
- if (f_code) {
- vl_vlc_needbits(&bs->vlc);
- delta += vl_vlc_ubits(&bs->vlc, f_code);
- vl_vlc_dumpbits(&bs->vlc, f_code);
+ if (has_sign) {
+ coeff.level = -coeff.level;
+ for(; i<(1 << (18 - coeff.length)); ++i)
+ dst[src->bitcode << 1 | i] = coeff;
}
-
- return (delta ^ sign) - sign;
}
}
-static INLINE int
-bound_motion_vector(int vec, unsigned f_code)
+static INLINE void
+init_tables()
{
-#if 1
- unsigned int limit;
- int sign;
-
- limit = 16 << f_code;
-
- if ((unsigned int)(vec + limit) < 2 * limit)
- return vec;
- else {
- sign = ((int32_t)vec) >> 31;
- return vec - ((2 * limit) ^ sign) + sign;
- }
-#else
- return ((int32_t)vec << (28 - f_code)) >> (28 - f_code);
-#endif
+ vl_vlc_init_table(tbl_B1, Elements(tbl_B1), macroblock_address_increment, Elements(macroblock_address_increment));
+ vl_vlc_init_table(tbl_B2, Elements(tbl_B2), macroblock_type_i, Elements(macroblock_type_i));
+ vl_vlc_init_table(tbl_B3, Elements(tbl_B3), macroblock_type_p, Elements(macroblock_type_p));
+ vl_vlc_init_table(tbl_B4, Elements(tbl_B4), macroblock_type_b, Elements(macroblock_type_b));
+ vl_vlc_init_table(tbl_B9, Elements(tbl_B9), coded_block_pattern, Elements(coded_block_pattern));
+ vl_vlc_init_table(tbl_B10, Elements(tbl_B10), motion_code, Elements(motion_code));
+ vl_vlc_init_table(tbl_B11, Elements(tbl_B11), dmvector, Elements(dmvector));
+ vl_vlc_init_table(tbl_B12, Elements(tbl_B12), dct_dc_size_luminance, Elements(dct_dc_size_luminance));
+ vl_vlc_init_table(tbl_B13, Elements(tbl_B13), dct_dc_size_chrominance, Elements(dct_dc_size_chrominance));
+ init_dct_coeff_table(tbl_B14_DC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), true);
+ init_dct_coeff_table(tbl_B14_AC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), false);
+ init_dct_coeff_table(tbl_B15, dct_coeff_tbl_one, Elements(dct_coeff_tbl_one), false);
}
static INLINE int
-get_dmv(struct vl_mpg12_bs *bs)
+DIV2DOWN(int todiv)
{
- const DMVtab * tab;
-
- tab = DMV_2 + vl_vlc_ubits(&bs->vlc, 2);
- vl_vlc_dumpbits(&bs->vlc, tab->len);
- return tab->dmv;
+ return (todiv&~1)/2;
}
static INLINE int
-get_coded_block_pattern(struct vl_mpg12_bs *bs)
+DIV2UP(int todiv)
{
- const CBPtab * tab;
-
- vl_vlc_needbits(&bs->vlc);
-
- if (bs->vlc.buf >= 0x20000000) {
-
- tab = CBP_7 + (vl_vlc_ubits(&bs->vlc, 7) - 16);
- vl_vlc_dumpbits(&bs->vlc, tab->len);
- return tab->cbp;
-
- } else {
-
- tab = CBP_9 + vl_vlc_ubits(&bs->vlc, 9);
- vl_vlc_dumpbits(&bs->vlc, tab->len);
- return tab->cbp;
- }
+ return (todiv+1)/2;
}
-static INLINE int
-get_luma_dc_dct_diff(struct vl_mpg12_bs *bs)
+static INLINE void
+motion_vector(struct vl_mpg12_bs *bs, int r, int s, int dmv, short delta[2], short dmvector[2])
{
- const DCtab * tab;
- int size;
- int dc_diff;
-
- if (bs->vlc.buf < 0xf8000000) {
- tab = DC_lum_5 + vl_vlc_ubits(&bs->vlc, 5);
- size = tab->size;
- if (size) {
- bs->vlc.bits += tab->len + size;
- bs->vlc.buf <<= tab->len;
- dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
- bs->vlc.buf <<= size;
- return dc_diff;
- } else {
- vl_vlc_dumpbits(&bs->vlc, 3);
- return 0;
- }
- } else {
- tab = DC_long + (vl_vlc_ubits(&bs->vlc, 9) - 0x1e0);
- size = tab->size;
- vl_vlc_dumpbits(&bs->vlc, tab->len);
- vl_vlc_needbits(&bs->vlc);
- dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
- vl_vlc_dumpbits(&bs->vlc, size);
- return dc_diff;
+ int t;
+ for (t = 0; t < 2; ++t) {
+ int motion_code;
+ int r_size = bs->desc.f_code[s][t];
+
+ vl_vlc_fillbits(&bs->vlc);
+ motion_code = vl_vlc_get_vlclbf(&bs->vlc, tbl_B10, 11);
+
+ assert(r_size >= 0);
+ if (r_size && motion_code) {
+ int residual = vl_vlc_get_uimsbf(&bs->vlc, r_size) + 1;
+ delta[t] = ((abs(motion_code) - 1) << r_size) + residual;
+ if (motion_code < 0)
+ delta[t] = -delta[t];
+ } else
+ delta[t] = motion_code;
+ if (dmv)
+ dmvector[t] = vl_vlc_get_vlclbf(&bs->vlc, tbl_B11, 2);
}
}
static INLINE int
-get_chroma_dc_dct_diff(struct vl_mpg12_bs *bs)
+wrap(short f, int shift)
{
- const DCtab * tab;
- int size;
- int dc_diff;
-
- if (bs->vlc.buf < 0xf8000000) {
- tab = DC_chrom_5 + vl_vlc_ubits(&bs->vlc, 5);
- size = tab->size;
- if (size) {
- bs->vlc.bits += tab->len + size;
- bs->vlc.buf <<= tab->len;
- dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
- bs->vlc.buf <<= size;
- return dc_diff;
- } else {
- vl_vlc_dumpbits(&bs->vlc, 2);
- return 0;
- }
- } else {
- tab = DC_long + (vl_vlc_ubits(&bs->vlc, 10) - 0x3e0);
- size = tab->size;
- vl_vlc_dumpbits(&bs->vlc, tab->len + 1);
- vl_vlc_needbits(&bs->vlc);
- dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
- vl_vlc_dumpbits(&bs->vlc, size);
- return dc_diff;
- }
+ if (f < (-16 << shift))
+ return f + (32 << shift);
+ else if (f >= 16 << shift)
+ return f - (32 << shift);
+ else
+ return f;
}
static INLINE void
-get_intra_block_B14(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+motion_vector_frame(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
{
- int i, val;
- const DCTtab *tab;
-
- i = 0;
-
- vl_vlc_needbits(&bs->vlc);
-
- while (1) {
- if (bs->vlc.buf >= 0x28000000) {
-
- tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-
- i += tab->run;
- if (i >= 64)
- break; /* end of block */
+ int dmv = mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
+ short dmvector[2], delta[2];
- normal_code:
- bs->vlc.buf <<= tab->len;
- bs->vlc.bits += tab->len + 1;
- val = tab->level * quantizer_scale;
+ if (mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_FIELD) {
+ mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
+ motion_vector(bs, 0, s, dmv, delta, dmvector);
+ mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc.f_code[s][0]);
+ mb->PMV[0][s][1] = wrap(DIV2DOWN(mb->PMV[0][s][1]) + delta[1], bs->desc.f_code[s][1]) * 2;
- val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
+ mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2);
+ motion_vector(bs, 1, s, dmv, delta, dmvector);
+ mb->PMV[1][s][0] = wrap(mb->PMV[1][s][0] + delta[0], bs->desc.f_code[s][0]);
+ mb->PMV[1][s][1] = wrap(DIV2DOWN(mb->PMV[1][s][1]) + delta[1], bs->desc.f_code[s][1]) * 2;
- dest[i] = val;
-
- bs->vlc.buf <<= 1;
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- } else if (bs->vlc.buf >= 0x04000000) {
-
- tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
- i += tab->run;
- if (i < 64)
- goto normal_code;
-
- /* escape code */
-
- i += UBITS(bs->vlc.buf << 6, 6) - 64;
- if (i >= 64)
- break; /* illegal, check needed to avoid buffer overflow */
-
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
- val = vl_vlc_sbits(&bs->vlc, 12) * quantizer_scale;
-
- dest[i] = val;
-
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- } else if (bs->vlc.buf >= 0x02000000) {
- tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00800000) {
- tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00200000) {
- tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else {
- tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
- bs->vlc.buf <<= 16;
- vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- }
- break; /* illegal, check needed to avoid buffer overflow */
+ } else {
+ motion_vector(bs, 0, s, dmv, delta, dmvector);
+ mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc.f_code[s][0]);
+ mb->PMV[0][s][1] = wrap(mb->PMV[0][s][1] + delta[1], bs->desc.f_code[s][1]);
}
-
- vl_vlc_dumpbits(&bs->vlc, 2); /* dump end of block code */
}
static INLINE void
-get_intra_block_B15(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+motion_vector_field(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
{
- int i, val;
- const DCTtab * tab;
-
- i = 0;
-
- vl_vlc_needbits(&bs->vlc);
-
- while (1) {
- if (bs->vlc.buf >= 0x04000000) {
-
- tab = DCT_B15_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
- i += tab->run;
- if (i < 64) {
-
- normal_code:
- bs->vlc.buf <<= tab->len;
- bs->vlc.bits += tab->len + 1;
- val = tab->level * quantizer_scale;
-
- val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
+ int dmv = mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
+ short dmvector[2], delta[2];
- dest[i] = val;
+ if (mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_16x8) {
+ mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
+ motion_vector(bs, 0, s, dmv, delta, dmvector);
- bs->vlc.buf <<= 1;
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- } else {
-
- /* end of block. I commented out this code because if we */
- /* dont exit here we will still exit at the later test :) */
-
- /* if (i >= 128) break; */ /* end of block */
-
- /* escape code */
-
- i += UBITS(bs->vlc.buf << 6, 6) - 64;
- if (i >= 64)
- break; /* illegal, check against buffer overflow */
-
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
- val = vl_vlc_sbits(&bs->vlc, 12) * quantizer_scale;
-
- dest[i] = val;
-
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- }
- } else if (bs->vlc.buf >= 0x02000000) {
- tab = DCT_B15_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00800000) {
- tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00200000) {
- tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else {
- tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
- bs->vlc.buf <<= 16;
- vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- }
- break; /* illegal, check needed to avoid buffer overflow */
+ mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2);
+ motion_vector(bs, 1, s, dmv, delta, dmvector);
+ } else {
+ if (!dmv)
+ mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
+ motion_vector(bs, 0, s, dmv, delta, dmvector);
}
-
- vl_vlc_dumpbits(&bs->vlc, 4); /* dump end of block code */
}
static INLINE void
-get_non_intra_block(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
-{
- int i, val;
- const DCTtab *tab;
-
- i = -1;
-
- vl_vlc_needbits(&bs->vlc);
- if (bs->vlc.buf >= 0x28000000) {
- tab = DCT_B14DC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
- goto entry_1;
- } else
- goto entry_2;
-
- while (1) {
- if (bs->vlc.buf >= 0x28000000) {
-
- tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-
- entry_1:
- i += tab->run;
- if (i >= 64)
- break; /* end of block */
-
- normal_code:
- bs->vlc.buf <<= tab->len;
- bs->vlc.bits += tab->len + 1;
- val = ((2*tab->level+1) * quantizer_scale) >> 1;
-
- val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
-
- dest[i] = val;
-
- bs->vlc.buf <<= 1;
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- }
-
- entry_2:
- if (bs->vlc.buf >= 0x04000000) {
-
- tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
- i += tab->run;
- if (i < 64)
- goto normal_code;
-
- /* escape code */
-
- i += UBITS(bs->vlc.buf << 6, 6) - 64;
- if (i >= 64)
- break; /* illegal, check needed to avoid buffer overflow */
-
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
- val = 2 * (vl_vlc_sbits(&bs->vlc, 12) + vl_vlc_sbits(&bs->vlc, 1)) + 1;
- val = (val * quantizer_scale) / 2;
-
- dest[i] = val;
-
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- } else if (bs->vlc.buf >= 0x02000000) {
- tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00800000) {
- tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00200000) {
- tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else {
- tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
- bs->vlc.buf <<= 16;
- vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- }
- break; /* illegal, check needed to avoid buffer overflow */
- }
- vl_vlc_dumpbits(&bs->vlc, 2); /* dump end of block code */
+reset_predictor(struct vl_mpg12_bs *bs) {
+ bs->pred_dc[0] = bs->pred_dc[1] = bs->pred_dc[2] = 0;
}
static INLINE void
-get_mpeg1_intra_block(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+decode_dct(struct vl_mpg12_bs *bs, struct pipe_mpeg12_macroblock *mb, int scale)
{
- int i, val;
- const DCTtab * tab;
-
- i = 0;
+ static const unsigned blk2cc[] = { 0, 0, 0, 0, 1, 2 };
+ static const struct vl_vlc_entry *blk2dcsize[] = {
+ tbl_B12, tbl_B12, tbl_B12, tbl_B12, tbl_B13, tbl_B13
+ };
- vl_vlc_needbits(&bs->vlc);
+ bool intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA;
+ const struct dct_coeff *table = intra ? bs->intra_dct_tbl : tbl_B14_AC;
+ const struct dct_coeff *entry;
+ int i, cbp, blk = 0;
+ short *dst = mb->blocks;
- while (1) {
- if (bs->vlc.buf >= 0x28000000) {
+ vl_vlc_fillbits(&bs->vlc);
+ mb->coded_block_pattern = cbp = intra ? 0x3F : vl_vlc_get_vlclbf(&bs->vlc, tbl_B9, 9);
- tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
+ goto entry;
- i += tab->run;
- if (i >= 64)
- break; /* end of block */
+ while(1) {
+ vl_vlc_eatbits(&bs->vlc, entry->length);
+ if (entry->run == dct_End_of_Block) {
- normal_code:
- bs->vlc.buf <<= tab->len;
- bs->vlc.bits += tab->len + 1;
- val = tab->level * quantizer_scale;
+ dst += 64;
+ cbp <<= 1;
+ cbp &= 0x3F;
+ blk++;
- /* oddification */
- val = (val - 1) | 1;
-
- /* if (bitstream_get (1)) val = -val; */
- val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
-
- dest[i] = val;
-
- bs->vlc.buf <<= 1;
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- } else if (bs->vlc.buf >= 0x04000000) {
-
- tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
- i += tab->run;
- if (i < 64)
- goto normal_code;
-
- /* escape code */
-
- i += UBITS(bs->vlc.buf << 6, 6) - 64;
- if (i >= 64)
- break; /* illegal, check needed to avoid buffer overflow */
+entry:
+ if (!cbp)
+ break;
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
- val = vl_vlc_sbits(&bs->vlc, 8);
- if (! (val & 0x7f)) {
- vl_vlc_dumpbits(&bs->vlc, 8);
- val = vl_vlc_ubits(&bs->vlc, 8) + 2 * val;
+ while(!(cbp & 0x20)) {
+ cbp <<= 1;
+ blk++;
}
- val = val * quantizer_scale;
-
- /* oddification */
- val = (val + ~SBITS (val, 1)) | 1;
-
- dest[i] = val;
-
- vl_vlc_dumpbits(&bs->vlc, 8);
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- } else if (bs->vlc.buf >= 0x02000000) {
- tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00800000) {
- tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00200000) {
- tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else {
- tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
- bs->vlc.buf <<= 16;
- vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- }
- break; /* illegal, check needed to avoid buffer overflow */
- }
- vl_vlc_dumpbits(&bs->vlc, 2); /* dump end of block code */
-}
-
-static INLINE void
-get_mpeg1_non_intra_block(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
-{
- int i, val;
- const DCTtab * tab;
-
- i = -1;
-
- vl_vlc_needbits(&bs->vlc);
- if (bs->vlc.buf >= 0x28000000) {
- tab = DCT_B14DC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
- goto entry_1;
- } else
- goto entry_2;
-
- while (1) {
- if (bs->vlc.buf >= 0x28000000) {
-
- tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-
- entry_1:
- i += tab->run;
- if (i >= 64)
- break; /* end of block */
- normal_code:
- bs->vlc.buf <<= tab->len;
- bs->vlc.bits += tab->len + 1;
- val = ((2*tab->level+1) * quantizer_scale) >> 1;
+ vl_vlc_fillbits(&bs->vlc);
- /* oddification */
- val = (val - 1) | 1;
+ if (intra) {
+ unsigned cc = blk2cc[blk];
+ unsigned size = vl_vlc_get_vlclbf(&bs->vlc, blk2dcsize[blk], 10);
- /* if (bitstream_get (1)) val = -val; */
- val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
-
- dest[i] = val;
-
- bs->vlc.buf <<= 1;
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- }
-
- entry_2:
- if (bs->vlc.buf >= 0x04000000) {
-
- tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
- i += tab->run;
- if (i < 64)
- goto normal_code;
-
- /* escape code */
+ if (size) {
+ int dct_diff = vl_vlc_get_uimsbf(&bs->vlc, size);
+ int half_range = 1 << (size - 1);
+ if (dct_diff < half_range)
+ dct_diff = (dct_diff + 1) - (2 * half_range);
+ bs->pred_dc[cc] += dct_diff;
+ }
- i += UBITS(bs->vlc.buf << 6, 6) - 64;
- if (i >= 64)
- break; /* illegal, check needed to avoid buffer overflow */
+ dst[0] = bs->pred_dc[cc];
+ i = 0;
- vl_vlc_dumpbits(&bs->vlc, 12);
- vl_vlc_needbits(&bs->vlc);
- val = vl_vlc_sbits(&bs->vlc, 8);
- if (! (val & 0x7f)) {
- vl_vlc_dumpbits(&bs->vlc, 8);
- val = vl_vlc_ubits(&bs->vlc, 8) + 2 * val;
+ } else {
+ entry = tbl_B14_DC + vl_vlc_peekbits(&bs->vlc, 17);
+ i = -1;
+ continue;
}
- val = 2 * (val + SBITS (val, 1)) + 1;
- val = (val * quantizer_scale) / 2;
-
- /* oddification */
- val = (val + ~SBITS (val, 1)) | 1;
-
- dest[i] = val;
-
- vl_vlc_dumpbits(&bs->vlc, 8);
- vl_vlc_needbits(&bs->vlc);
-
- continue;
-
- } else if (bs->vlc.buf >= 0x02000000) {
- tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00800000) {
- tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else if (bs->vlc.buf >= 0x00200000) {
- tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- } else {
- tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
- bs->vlc.buf <<= 16;
- vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
- i += tab->run;
- if (i < 64)
- goto normal_code;
- }
- break; /* illegal, check needed to avoid buffer overflow */
- }
- vl_vlc_dumpbits(&bs->vlc, 2); /* dump end of block code */
-}
-
-static INLINE void
-slice_intra_DCT(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture, int cc,
- unsigned x, unsigned y, enum pipe_mpeg12_dct_type coding, int quantizer_scale, int dc_dct_pred[3])
-{
- short dest[64];
-
- bs->ycbcr_stream[cc]->x = x;
- bs->ycbcr_stream[cc]->y = y;
- bs->ycbcr_stream[cc]->intra = PIPE_MPEG12_DCT_INTRA;
- bs->ycbcr_stream[cc]->coding = coding;
-
- vl_vlc_needbits(&bs->vlc);
-
- /* Get the intra DC coefficient and inverse quantize it */
- if (cc == 0)
- dc_dct_pred[0] += get_luma_dc_dct_diff(bs);
- else
- dc_dct_pred[cc] += get_chroma_dc_dct_diff(bs);
-
- memset(dest, 0, sizeof(int16_t) * 64);
- dest[0] = dc_dct_pred[cc];
- if (picture->base.profile == PIPE_VIDEO_PROFILE_MPEG1) {
- if (picture->picture_coding_type != D_TYPE)
- get_mpeg1_intra_block(bs, quantizer_scale, dest);
- } else if (picture->intra_vlc_format)
- get_intra_block_B15(bs, quantizer_scale, dest);
- else
- get_intra_block_B14(bs, quantizer_scale, dest);
-
- memcpy(bs->ycbcr_buffer[cc], dest, sizeof(int16_t) * 64);
-
- bs->num_ycbcr_blocks[cc]++;
- bs->ycbcr_stream[cc]++;
- bs->ycbcr_buffer[cc] += 64;
-}
-
-static INLINE void
-slice_non_intra_DCT(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture, int cc,
- unsigned x, unsigned y, enum pipe_mpeg12_dct_type coding, int quantizer_scale)
-{
- short dest[64];
-
- bs->ycbcr_stream[cc]->x = x;
- bs->ycbcr_stream[cc]->y = y;
- bs->ycbcr_stream[cc]->intra = PIPE_MPEG12_DCT_DELTA;
- bs->ycbcr_stream[cc]->coding = coding;
-
- memset(dest, 0, sizeof(int16_t) * 64);
- if (picture->base.profile == PIPE_VIDEO_PROFILE_MPEG1)
- get_mpeg1_non_intra_block(bs, quantizer_scale, dest);
- else
- get_non_intra_block(bs, quantizer_scale, dest);
-
- memcpy(bs->ycbcr_buffer[cc], dest, sizeof(int16_t) * 64);
-
- bs->num_ycbcr_blocks[cc]++;
- bs->ycbcr_stream[cc]++;
- bs->ycbcr_buffer[cc] += 64;
-}
-
-static INLINE void
-motion_mp1(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int motion_x, motion_y;
-
- mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
- vl_vlc_needbits(&bs->vlc);
- motion_x = (mv->top.x + (get_motion_delta(bs, f_code[0]) << f_code[1]));
- motion_x = bound_motion_vector (motion_x, f_code[0] + f_code[1]);
- mv->top.x = mv->bottom.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = (mv->top.y + (get_motion_delta(bs, f_code[0]) << f_code[1]));
- motion_y = bound_motion_vector (motion_y, f_code[0] + f_code[1]);
- mv->top.y = mv->bottom.y = motion_y;
-}
-
-static INLINE void
-motion_fr_frame(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int motion_x, motion_y;
-
- mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
- vl_vlc_needbits(&bs->vlc);
- motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector(motion_x, f_code[0]);
- mv->top.x = mv->bottom.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
- motion_y = bound_motion_vector(motion_y, f_code[1]);
- mv->top.y = mv->bottom.y = motion_y;
-}
-
-static INLINE void
-motion_fr_field(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int motion_x, motion_y;
-
- vl_vlc_needbits(&bs->vlc);
- mv->top.field_select = vl_vlc_ubits(&bs->vlc, 1) ?
- PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
- vl_vlc_dumpbits(&bs->vlc, 1);
-
- motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector (motion_x, f_code[0]);
- mv->top.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = (mv->top.y >> 1) + get_motion_delta(bs, f_code[1]);
- /* motion_y = bound_motion_vector (motion_y, f_code[1]); */
- mv->top.y = motion_y << 1;
-
- vl_vlc_needbits(&bs->vlc);
- mv->bottom.field_select = vl_vlc_ubits(&bs->vlc, 1) ?
- PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
- vl_vlc_dumpbits(&bs->vlc, 1);
-
- motion_x = mv->bottom.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector (motion_x, f_code[0]);
- mv->bottom.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = (mv->bottom.y >> 1) + get_motion_delta(bs, f_code[1]);
- /* motion_y = bound_motion_vector (motion_y, f_code[1]); */
- mv->bottom.y = motion_y << 1;
-}
-
-static INLINE void
-motion_fr_dmv(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int motion_x, motion_y;
-
- // TODO Implement dmv
- mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
- vl_vlc_needbits(&bs->vlc);
- motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector(motion_x, f_code[0]);
- mv->top.x = mv->bottom.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = (mv->top.y >> 1) + get_motion_delta(bs, f_code[1]);
- /* motion_y = bound_motion_vector (motion_y, f_code[1]); */
- mv->top.y = mv->bottom.y = motion_y << 1;
-}
-
-/* like motion_frame, but parsing without actual motion compensation */
-static INLINE void
-motion_fr_conceal(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int tmp;
-
- mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
- vl_vlc_needbits(&bs->vlc);
- tmp = (mv->top.x + get_motion_delta(bs, f_code[0]));
- tmp = bound_motion_vector (tmp, f_code[0]);
- mv->top.x = mv->bottom.x = tmp;
-
- vl_vlc_needbits(&bs->vlc);
- tmp = (mv->top.y + get_motion_delta(bs, f_code[1]));
- tmp = bound_motion_vector (tmp, f_code[1]);
- mv->top.y = mv->bottom.y = tmp;
-
- vl_vlc_dumpbits(&bs->vlc, 1); /* remove marker_bit */
-}
-
-static INLINE void
-motion_fi_field(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int motion_x, motion_y;
-
- vl_vlc_needbits(&bs->vlc);
-
- // ref_field
- //vl_vlc_ubits(&bs->vlc, 1);
-
- // TODO field select may need to do something here for bob (weave ok)
- mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
- vl_vlc_dumpbits(&bs->vlc, 1);
-
- motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector (motion_x, f_code[0]);
- mv->top.x = mv->bottom.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
- motion_y = bound_motion_vector (motion_y, f_code[1]);
- mv->top.y = mv->bottom.y = motion_y;
-}
-
-static INLINE void
-motion_fi_16x8(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int motion_x, motion_y;
-
- vl_vlc_needbits(&bs->vlc);
-
- // ref_field
- //vl_vlc_ubits(&bs->vlc, 1);
-
- // TODO field select may need to do something here bob (weave ok)
- mv->top.field_select = PIPE_VIDEO_FRAME;
- vl_vlc_dumpbits(&bs->vlc, 1);
-
- motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector (motion_x, f_code[0]);
- mv->top.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
- motion_y = bound_motion_vector (motion_y, f_code[1]);
- mv->top.y = motion_y;
-
- vl_vlc_needbits(&bs->vlc);
- // ref_field
- //vl_vlc_ubits(&bs->vlc, 1);
-
- // TODO field select may need to do something here for bob (weave ok)
- mv->bottom.field_select = PIPE_VIDEO_FRAME;
- vl_vlc_dumpbits(&bs->vlc, 1);
-
- motion_x = mv->bottom.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector (motion_x, f_code[0]);
- mv->bottom.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = mv->bottom.y + get_motion_delta(bs, f_code[1]);
- motion_y = bound_motion_vector (motion_y, f_code[1]);
- mv->bottom.y = motion_y;
-}
-
-static INLINE void
-motion_fi_dmv(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int motion_x, motion_y;
-
- // TODO field select may need to do something here for bob (weave ok)
- mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
- vl_vlc_needbits(&bs->vlc);
- motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
- motion_x = bound_motion_vector (motion_x, f_code[0]);
- mv->top.x = mv->bottom.x = motion_x;
-
- vl_vlc_needbits(&bs->vlc);
- motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
- motion_y = bound_motion_vector (motion_y, f_code[1]);
- mv->top.y = mv->bottom.y = motion_y;
-}
-
-
-static INLINE void
-motion_fi_conceal(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
- int tmp;
- vl_vlc_needbits(&bs->vlc);
- vl_vlc_dumpbits(&bs->vlc, 1); /* remove field_select */
-
- tmp = (mv->top.x + get_motion_delta(bs, f_code[0]));
- tmp = bound_motion_vector(tmp, f_code[0]);
- mv->top.x = mv->bottom.x = tmp;
-
- vl_vlc_needbits(&bs->vlc);
- tmp = (mv->top.y + get_motion_delta(bs, f_code[1]));
- tmp = bound_motion_vector(tmp, f_code[1]);
- mv->top.y = mv->bottom.y = tmp;
-
- vl_vlc_dumpbits(&bs->vlc, 1); /* remove marker_bit */
-}
-
-#define MOTION_CALL(routine, macroblock_modes) \
-do { \
- if ((macroblock_modes) & MACROBLOCK_MOTION_FORWARD) \
- routine(bs, picture->f_code[0], &mv_fwd); \
- if ((macroblock_modes) & MACROBLOCK_MOTION_BACKWARD) \
- routine(bs, picture->f_code[1], &mv_bwd); \
-} while (0)
-
-static INLINE void
-store_motionvectors(struct vl_mpg12_bs *bs, unsigned *mv_pos,
- struct pipe_motionvector *mv_fwd,
- struct pipe_motionvector *mv_bwd)
-{
- bs->mv_stream[0][*mv_pos].top = mv_fwd->top;
- bs->mv_stream[0][*mv_pos].bottom =
- mv_fwd->top.field_select == PIPE_VIDEO_FRAME ?
- mv_fwd->top : mv_fwd->bottom;
-
- bs->mv_stream[1][*mv_pos].top = mv_bwd->top;
- bs->mv_stream[1][*mv_pos].bottom =
- mv_bwd->top.field_select == PIPE_VIDEO_FRAME ?
- mv_bwd->top : mv_bwd->bottom;
-
- (*mv_pos)++;
-}
-
-static INLINE bool
-slice_init(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture,
- int *quantizer_scale, unsigned *x, unsigned *y, unsigned *mv_pos)
-{
- const MBAtab * mba;
-
- vl_vlc_need32bits(&bs->vlc);
- while(bs->vlc.buf < 0x101 || bs->vlc.buf > 0x1AF) {
- if(!vl_vlc_getbyte(&bs->vlc))
- return false;
- }
- *y = (bs->vlc.buf & 0xFF) - 1;
- vl_vlc_restart(&bs->vlc);
+ } else if (entry->run == dct_Escape) {
+ i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
+ if (i > 64)
+ break;
- *quantizer_scale = get_quantizer_scale(bs, picture);
+ dst[i] = vl_vlc_get_simsbf(&bs->vlc, 12) * scale;
- /* ignore intra_slice and all the extra data */
- while (bs->vlc.buf & 0x80000000) {
- vl_vlc_dumpbits(&bs->vlc, 9);
- vl_vlc_needbits(&bs->vlc);
- }
+ } else {
+ i += entry->run;
+ if (i > 64)
+ break;
- /* decode initial macroblock address increment */
- *x = 0;
- while (1) {
- if (bs->vlc.buf >= 0x08000000) {
- mba = MBA_5 + (vl_vlc_ubits(&bs->vlc, 6) - 2);
- break;
- } else if (bs->vlc.buf >= 0x01800000) {
- mba = MBA_11 + (vl_vlc_ubits(&bs->vlc, 12) - 24);
- break;
- } else switch (vl_vlc_ubits(&bs->vlc, 12)) {
- case 8: /* macroblock_escape */
- *x += 33;
- vl_vlc_dumpbits(&bs->vlc, 11);
- vl_vlc_needbits(&bs->vlc);
- continue;
- case 15: /* macroblock_stuffing (MPEG1 only) */
- bs->vlc.buf &= 0xfffff;
- vl_vlc_dumpbits(&bs->vlc, 11);
- vl_vlc_needbits(&bs->vlc);
- continue;
- default: /* error */
- return false;
+ dst[i] = entry->level * scale;
}
- }
- vl_vlc_dumpbits(&bs->vlc, mba->len + 1);
- *x += mba->mba;
- while (*x >= bs->width) {
- *x -= bs->width;
- (*y)++;
+ vl_vlc_fillbits(&bs->vlc);
+ entry = table + vl_vlc_peekbits(&bs->vlc, 17);
}
- if (*y > bs->height)
- return false;
-
- *mv_pos = *x + *y * bs->width;
-
- return true;
}
static INLINE bool
-decode_slice(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc *picture)
+decode_slice(struct vl_mpg12_bs *bs)
{
- enum pipe_video_field_select default_field_select;
- struct pipe_motionvector mv_fwd, mv_bwd;
- enum pipe_mpeg12_dct_type dct_type;
-
- /* predictor for DC coefficients in intra blocks */
- int dc_dct_pred[3] = { 0, 0, 0 };
- int quantizer_scale;
+ struct pipe_mpeg12_macroblock mb;
+ short dct_blocks[64*6];
+ unsigned dct_scale;
+ signed x = -1;
- unsigned x, y, mv_pos;
+ memset(&mb, 0, sizeof(mb));
+ mb.base.codec = PIPE_VIDEO_CODEC_MPEG12;
+ mb.y = vl_vlc_get_uimsbf(&bs->vlc, 8) - 1;
+ mb.blocks = dct_blocks;
- switch(picture->picture_structure) {
- case TOP_FIELD:
- default_field_select = PIPE_VIDEO_TOP_FIELD;
- break;
+ reset_predictor(bs);
+ dct_scale = quant_scale[bs->desc.q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)];
- case BOTTOM_FIELD:
- default_field_select = PIPE_VIDEO_BOTTOM_FIELD;
- break;
+ if (vl_vlc_get_uimsbf(&bs->vlc, 1))
+ while (vl_vlc_get_uimsbf(&bs->vlc, 9) & 1)
+ vl_vlc_fillbits(&bs->vlc);
- default:
- default_field_select = PIPE_VIDEO_FRAME;
- break;
- }
-
- if (!slice_init(bs, picture, &quantizer_scale, &x, &y, &mv_pos))
- return false;
+ do {
+ int inc = 0;
- mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
- mv_fwd.top.field_select = mv_fwd.bottom.field_select = default_field_select;
+ vl_vlc_fillbits(&bs->vlc);
- mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
- mv_bwd.top.field_select = mv_bwd.bottom.field_select = default_field_select;
+ while (vl_vlc_peekbits(&bs->vlc, 11) == 15) {
+ vl_vlc_eatbits(&bs->vlc, 11);
+ vl_vlc_fillbits(&bs->vlc);
+ }
- while (1) {
- int macroblock_modes;
- int mba_inc;
- const MBAtab * mba;
+ while (vl_vlc_peekbits(&bs->vlc, 11) == 8) {
+ vl_vlc_eatbits(&bs->vlc, 11);
+ vl_vlc_fillbits(&bs->vlc);
+ inc += 33;
+ }
+ inc += vl_vlc_get_vlclbf(&bs->vlc, tbl_B1, 11);
+ if (x != -1) {
+ mb.num_skipped_macroblocks = inc - 1;
+ bs->decoder->decode_macroblock(bs->decoder, &mb.base, 1);
+ }
+ mb.x = x += inc;
- vl_vlc_needbits(&bs->vlc);
+ switch (bs->desc.picture_coding_type) {
+ case PIPE_MPEG12_PICTURE_CODING_TYPE_I:
+ mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B2, 2);
+ break;
- macroblock_modes = get_macroblock_modes(bs, picture);
- dct_type = get_dct_type(bs, picture, macroblock_modes);
+ case PIPE_MPEG12_PICTURE_CODING_TYPE_P:
+ mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B3, 6);
+ break;
- switch(macroblock_modes & (MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD)) {
- case (MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD):
- mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_HALF;
- mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_HALF;
+ case PIPE_MPEG12_PICTURE_CODING_TYPE_B:
+ mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B4, 6);
break;
default:
- mv_fwd.top.field_select = mv_fwd.bottom.field_select = default_field_select;
- mv_bwd.top.field_select = mv_bwd.bottom.field_select = default_field_select;
+ mb.macroblock_type = 0;
+ /* dumb gcc */
+ assert(0);
+ }
- /* fall through */
- case MACROBLOCK_MOTION_FORWARD:
- mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
- mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
- break;
+ mb.macroblock_modes.value = 0;
+ if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) {
+ if (bs->desc.picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) {
+ if (bs->desc.frame_pred_frame_dct == 0)
+ mb.macroblock_modes.bits.frame_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2);
+ else
+ mb.macroblock_modes.bits.frame_motion_type = 2;
+ } else
+ mb.macroblock_modes.bits.field_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2);
- case MACROBLOCK_MOTION_BACKWARD:
- mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
- mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
- break;
+ } else if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) && bs->desc.concealment_motion_vectors) {
+ if (bs->desc.picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
+ mb.macroblock_modes.bits.frame_motion_type = 2;
+ else
+ mb.macroblock_modes.bits.field_motion_type = 1;
}
- /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */
- if (macroblock_modes & MACROBLOCK_QUANT)
- quantizer_scale = get_quantizer_scale(bs, picture);
-
- if (macroblock_modes & MACROBLOCK_INTRA) {
+ if (bs->desc.picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME &&
+ bs->desc.frame_pred_frame_dct == 0 &&
+ mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN))
+ mb.macroblock_modes.bits.dct_type = vl_vlc_get_uimsbf(&bs->vlc, 1);
- if (picture->concealment_motion_vectors) {
- if (picture->picture_structure == FRAME_PICTURE)
- motion_fr_conceal(bs, picture->f_code[0], &mv_fwd);
- else
- motion_fi_conceal(bs, picture->f_code[0], &mv_fwd);
+ if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_QUANT)
+ dct_scale = quant_scale[bs->desc.q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)];
- } else {
- mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
- mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
- }
- mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
- mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
-
- // unravaled loop of 6 block(i) calls in macroblock()
- slice_intra_DCT(bs, picture, 0, x*2+0, y*2+0, dct_type, quantizer_scale, dc_dct_pred);
- slice_intra_DCT(bs, picture, 0, x*2+1, y*2+0, dct_type, quantizer_scale, dc_dct_pred);
- slice_intra_DCT(bs, picture, 0, x*2+0, y*2+1, dct_type, quantizer_scale, dc_dct_pred);
- slice_intra_DCT(bs, picture, 0, x*2+1, y*2+1, dct_type, quantizer_scale, dc_dct_pred);
- slice_intra_DCT(bs, picture, 1, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale, dc_dct_pred);
- slice_intra_DCT(bs, picture, 2, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale, dc_dct_pred);
-
- if (picture->picture_coding_type == D_TYPE) {
- vl_vlc_needbits(&bs->vlc);
- vl_vlc_dumpbits(&bs->vlc, 1);
- }
+ if (inc > 1 && bs->desc.picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_P)
+ memset(mb.PMV, 0, sizeof(mb.PMV));
- } else {
- if (picture->picture_structure == FRAME_PICTURE)
- switch (macroblock_modes & MOTION_TYPE_MASK) {
- case MC_FRAME:
- if (picture->base.profile == PIPE_VIDEO_PROFILE_MPEG1) {
- MOTION_CALL(motion_mp1, macroblock_modes);
- } else {
- MOTION_CALL(motion_fr_frame, macroblock_modes);
- }
- break;
-
- case MC_FIELD:
- MOTION_CALL (motion_fr_field, macroblock_modes);
- break;
-
- case MC_DMV:
- MOTION_CALL (motion_fr_dmv, MACROBLOCK_MOTION_FORWARD);
- break;
-
- case 0:
- /* non-intra mb without forward mv in a P picture */
- mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
- mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
- break;
- }
+ mb.motion_vertical_field_select = 0;
+ if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD) ||
+ (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc.concealment_motion_vectors)) {
+ if (bs->desc.picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
+ motion_vector_frame(bs, 0, &mb);
else
- switch (macroblock_modes & MOTION_TYPE_MASK) {
- case MC_FIELD:
- MOTION_CALL (motion_fi_field, macroblock_modes);
- break;
-
- case MC_16X8:
- MOTION_CALL (motion_fi_16x8, macroblock_modes);
- break;
-
- case MC_DMV:
- MOTION_CALL (motion_fi_dmv, MACROBLOCK_MOTION_FORWARD);
- break;
-
- case 0:
- /* non-intra mb without forward mv in a P picture */
- mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
- mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
- break;
- }
-
- if (macroblock_modes & MACROBLOCK_PATTERN) {
- int coded_block_pattern = get_coded_block_pattern(bs);
-
- // TODO optimize not fully used for idct accel only mc.
- if (coded_block_pattern & 0x20)
- slice_non_intra_DCT(bs, picture, 0, x*2+0, y*2+0, dct_type, quantizer_scale); // cc0 luma 0
- if (coded_block_pattern & 0x10)
- slice_non_intra_DCT(bs, picture, 0, x*2+1, y*2+0, dct_type, quantizer_scale); // cc0 luma 1
- if (coded_block_pattern & 0x08)
- slice_non_intra_DCT(bs, picture, 0, x*2+0, y*2+1, dct_type, quantizer_scale); // cc0 luma 2
- if (coded_block_pattern & 0x04)
- slice_non_intra_DCT(bs, picture, 0, x*2+1, y*2+1, dct_type, quantizer_scale); // cc0 luma 3
- if (coded_block_pattern & 0x2)
- slice_non_intra_DCT(bs, picture, 1, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale); // cc1 croma
- if (coded_block_pattern & 0x1)
- slice_non_intra_DCT(bs, picture, 2, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale); // cc2 croma
- }
-
- dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0;
+ motion_vector_field(bs, 0, &mb);
}
- store_motionvectors(bs, &mv_pos, &mv_fwd, &mv_bwd);
- if (++x >= bs->width) {
- ++y;
- if (y >= bs->height)
- return false;
- x -= bs->width;
+ if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD) {
+ if (bs->desc.picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
+ motion_vector_frame(bs, 1, &mb);
+ else
+ motion_vector_field(bs, 1, &mb);
}
- vl_vlc_needbits(&bs->vlc);
- mba_inc = 0;
- while (1) {
- if (bs->vlc.buf >= 0x10000000) {
- mba = MBA_5 + (vl_vlc_ubits(&bs->vlc, 5) - 2);
- break;
- } else if (bs->vlc.buf >= 0x03000000) {
- mba = MBA_11 + (vl_vlc_ubits(&bs->vlc, 11) - 24);
- break;
- } else switch (vl_vlc_ubits(&bs->vlc, 11)) {
- case 8: /* macroblock_escape */
- mba_inc += 33;
- /* pass through */
- case 15: /* macroblock_stuffing (MPEG1 only) */
- vl_vlc_dumpbits(&bs->vlc, 11);
- vl_vlc_needbits(&bs->vlc);
- continue;
- default: /* end of slice, or error */
- return true;
- }
+ if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc.concealment_motion_vectors) {
+ unsigned extra = vl_vlc_get_uimsbf(&bs->vlc, 1);
+ mb.PMV[1][0][0] = mb.PMV[0][0][0];
+ mb.PMV[1][0][1] = mb.PMV[0][0][1];
+ assert(extra);
+ } else if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA ||
+ !(mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD |
+ PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD))) {
+ memset(mb.PMV, 0, sizeof(mb.PMV));
}
- vl_vlc_dumpbits(&bs->vlc, mba->len);
- mba_inc += mba->mba;
- if (mba_inc) {
- //TODO conversion to signed format signed format
- dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0;
-
- mv_fwd.top.field_select = mv_fwd.bottom.field_select = default_field_select;
- mv_bwd.top.field_select = mv_bwd.bottom.field_select = default_field_select;
-
- if (picture->picture_coding_type == P_TYPE) {
- mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
- mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
- }
- x += mba_inc;
- do {
- store_motionvectors(bs, &mv_pos, &mv_fwd, &mv_bwd);
- } while (--mba_inc);
+ if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD &&
+ mb.macroblock_modes.bits.frame_motion_type == 2) ||
+ (mb.macroblock_modes.bits.frame_motion_type == 3)) {
+ mb.PMV[1][0][0] = mb.PMV[0][0][0];
+ mb.PMV[1][0][1] = mb.PMV[0][0][1];
}
- while (x >= bs->width) {
- ++y;
- if (y >= bs->height)
- return false;
- x -= bs->width;
+
+ if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD &&
+ mb.macroblock_modes.bits.frame_motion_type == 2) {
+ mb.PMV[1][1][0] = mb.PMV[0][1][0];
+ mb.PMV[1][1][1] = mb.PMV[0][1][1];
}
- }
+
+ if (inc > 1 || !(mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA))
+ reset_predictor(bs);
+
+ if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN)) {
+ memset(dct_blocks, 0, sizeof(dct_blocks));
+ decode_dct(bs, &mb, dct_scale);
+ } else
+ mb.coded_block_pattern = 0;
+
+ } while (vl_vlc_bytes_left(&bs->vlc) && vl_vlc_peekbits(&bs->vlc, 23));
+
+ mb.num_skipped_macroblocks = 0;
+ bs->decoder->decode_macroblock(bs->decoder, &mb.base, 1);
+ return true;
}
void
-vl_mpg12_bs_init(struct vl_mpg12_bs *bs, unsigned width, unsigned height)
+vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_decoder *decoder)
{
+ static bool tables_initialized = false;
+
assert(bs);
memset(bs, 0, sizeof(struct vl_mpg12_bs));
- bs->width = width;
- bs->height = height;
+ bs->decoder = decoder;
+
+ if (!tables_initialized) {
+ init_tables();
+ tables_initialized = true;
+ }
}
void
-vl_mpg12_bs_set_buffers(struct vl_mpg12_bs *bs, struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES],
- short *ycbcr_buffer[VL_MAX_PLANES], struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES])
+vl_mpg12_bs_set_picture_desc(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc *picture)
{
- unsigned i;
-
- assert(bs);
- assert(ycbcr_stream && ycbcr_buffer);
- assert(mv_stream);
-
- for (i = 0; i < VL_MAX_PLANES; ++i) {
- bs->ycbcr_stream[i] = ycbcr_stream[i];
- bs->ycbcr_buffer[i] = ycbcr_buffer[i];
- }
- for (i = 0; i < VL_MAX_REF_FRAMES; ++i)
- bs->mv_stream[i] = mv_stream[i];
-
- // TODO
- for (i = 0; i < bs->width*bs->height; ++i) {
- bs->mv_stream[0][i].top.x = bs->mv_stream[0][i].top.y = 0;
- bs->mv_stream[0][i].top.field_select = PIPE_VIDEO_FRAME;
- bs->mv_stream[0][i].top.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
- bs->mv_stream[0][i].bottom.x = bs->mv_stream[0][i].bottom.y = 0;
- bs->mv_stream[0][i].bottom.field_select = PIPE_VIDEO_FRAME;
- bs->mv_stream[0][i].bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
-
- bs->mv_stream[1][i].top.x = bs->mv_stream[1][i].top.y = 0;
- bs->mv_stream[1][i].top.field_select = PIPE_VIDEO_FRAME;
- bs->mv_stream[1][i].top.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
- bs->mv_stream[1][i].bottom.x = bs->mv_stream[1][i].bottom.y = 0;
- bs->mv_stream[1][i].bottom.field_select = PIPE_VIDEO_FRAME;
- bs->mv_stream[1][i].bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
- }
+ bs->desc = *picture;
+ bs->intra_dct_tbl = picture->intra_vlc_format ? tbl_B15 : tbl_B14_AC;
}
void
-vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const void *buffer,
- struct pipe_mpeg12_picture_desc *picture, unsigned num_ycbcr_blocks[3])
+vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const uint8_t *buffer)
{
assert(bs);
- assert(num_ycbcr_blocks);
assert(buffer && num_bytes);
- bs->num_ycbcr_blocks = num_ycbcr_blocks;
+ while(num_bytes > 2) {
+ if (buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0x01 &&
+ buffer[3] >= 0x01 && buffer[3] < 0xAF) {
+ unsigned consumed;
+
+ buffer += 3;
+ num_bytes -= 3;
+
+ vl_vlc_init(&bs->vlc, buffer, num_bytes);
+
+ if (!decode_slice(bs))
+ return;
- vl_vlc_init(&bs->vlc, buffer, num_bytes);
+ /* it's possible for the vlc to consume up to eight extra bytes */
+ consumed = num_bytes - vl_vlc_bytes_left(&bs->vlc);
+ consumed = consumed > 8 ? consumed - 8 : 0;
- while(decode_slice(bs, picture));
+ /* crap, this is a bug we have consumed more bytes than left in the buffer */
+ assert(consumed <= num_bytes);
+
+ num_bytes -= consumed;
+ buffer += consumed;
+
+ } else {
+ ++buffer;
+ --num_bytes;
+ }
+ }
}
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.h b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.h
index 4e48a9faa2f..c3f14a17932 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.h
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.h
@@ -33,27 +33,22 @@
struct vl_mpg12_bs
{
- unsigned width, height;
+ struct pipe_video_decoder *decoder;
- struct vl_vlc vlc;
-
- unsigned *num_ycbcr_blocks;
+ struct pipe_mpeg12_picture_desc desc;
+ struct dct_coeff *intra_dct_tbl;
- struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES];
- short *ycbcr_buffer[VL_MAX_PLANES];
-
- struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES];
+ struct vl_vlc vlc;
+ short pred_dc[3];
};
void
-vl_mpg12_bs_init(struct vl_mpg12_bs *bs, unsigned width, unsigned height);
+vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_decoder *decoder);
void
-vl_mpg12_bs_set_buffers(struct vl_mpg12_bs *bs, struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES],
- short *ycbcr_buffer[VL_MAX_PLANES], struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES]);
+vl_mpg12_bs_set_picture_desc(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc *picture);
void
-vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const void *buffer,
- struct pipe_mpeg12_picture_desc *picture, unsigned num_ycbcr_blocks[3]);
+vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const uint8_t *buffer);
#endif /* vl_mpeg12_bitstream_h */
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c
index 61d947ca4c8..7d53168afe5 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c
@@ -30,6 +30,7 @@
#include <util/u_memory.h>
#include <util/u_rect.h>
+#include <util/u_sampler.h>
#include <util/u_video.h>
#include "vl_mpeg12_decoder.h"
@@ -75,36 +76,44 @@ static const struct format_config mc_format_config[] = {
static const unsigned num_mc_format_configs =
sizeof(mc_format_config) / sizeof(struct format_config);
+static const unsigned const_empty_block_mask_420[3][2][2] = {
+ { { 0x20, 0x10 }, { 0x08, 0x04 } },
+ { { 0x02, 0x02 }, { 0x02, 0x02 } },
+ { { 0x01, 0x01 }, { 0x01, 0x01 } }
+};
+
static bool
-init_zscan_buffer(struct vl_mpeg12_buffer *buffer)
+init_zscan_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buffer)
{
- enum pipe_format formats[3];
-
- struct pipe_sampler_view **source;
+ struct pipe_resource *res, res_tmpl;
+ struct pipe_sampler_view sv_tmpl;
struct pipe_surface **destination;
- struct vl_mpeg12_decoder *dec;
-
unsigned i;
- assert(buffer);
-
- dec = (struct vl_mpeg12_decoder*)buffer->base.decoder;
+ assert(dec && buffer);
- formats[0] = formats[1] = formats[2] = dec->zscan_source_format;
- buffer->zscan_source = vl_video_buffer_create_ex
- (
- dec->base.context,
- dec->blocks_per_line * BLOCK_WIDTH * BLOCK_HEIGHT,
- align(dec->num_blocks, dec->blocks_per_line) / dec->blocks_per_line,
- 1, PIPE_VIDEO_CHROMA_FORMAT_444, formats, PIPE_USAGE_STATIC
- );
+ memset(&res_tmpl, 0, sizeof(res_tmpl));
+ res_tmpl.target = PIPE_TEXTURE_2D;
+ res_tmpl.format = dec->zscan_source_format;
+ res_tmpl.width0 = dec->blocks_per_line * BLOCK_WIDTH * BLOCK_HEIGHT;
+ res_tmpl.height0 = align(dec->num_blocks, dec->blocks_per_line) / dec->blocks_per_line;
+ res_tmpl.depth0 = 1;
+ res_tmpl.array_size = 1;
+ res_tmpl.usage = PIPE_USAGE_STREAM;
+ res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
- if (!buffer->zscan_source)
+ res = dec->base.context->screen->resource_create(dec->base.context->screen, &res_tmpl);
+ if (!res)
goto error_source;
- source = buffer->zscan_source->get_sampler_view_planes(buffer->zscan_source);
- if (!source)
+
+ memset(&sv_tmpl, 0, sizeof(sv_tmpl));
+ u_sampler_view_default_template(&sv_tmpl, res, res->format);
+ sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = PIPE_SWIZZLE_RED;
+ buffer->zscan_source = dec->base.context->create_sampler_view(dec->base.context, res, &sv_tmpl);
+ pipe_resource_reference(&res, NULL);
+ if (!buffer->zscan_source)
goto error_sampler;
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
@@ -117,7 +126,7 @@ init_zscan_buffer(struct vl_mpeg12_buffer *buffer)
for (i = 0; i < VL_MAX_PLANES; ++i)
if (!vl_zscan_init_buffer(i == 0 ? &dec->zscan_y : &dec->zscan_c,
- &buffer->zscan[i], source[i], destination[i]))
+ &buffer->zscan[i], buffer->zscan_source, destination[i]))
goto error_plane;
return true;
@@ -128,7 +137,7 @@ error_plane:
error_surface:
error_sampler:
- buffer->zscan_source->destroy(buffer->zscan_source);
+ pipe_sampler_view_reference(&buffer->zscan_source, NULL);
error_source:
return false;
@@ -143,21 +152,18 @@ cleanup_zscan_buffer(struct vl_mpeg12_buffer *buffer)
for (i = 0; i < VL_MAX_PLANES; ++i)
vl_zscan_cleanup_buffer(&buffer->zscan[i]);
- buffer->zscan_source->destroy(buffer->zscan_source);
+
+ pipe_sampler_view_reference(&buffer->zscan_source, NULL);
}
static bool
-init_idct_buffer(struct vl_mpeg12_buffer *buffer)
+init_idct_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buffer)
{
struct pipe_sampler_view **idct_source_sv, **mc_source_sv;
- struct vl_mpeg12_decoder *dec;
-
unsigned i;
- assert(buffer);
-
- dec = (struct vl_mpeg12_decoder*)buffer->base.decoder;
+ assert(dec && buffer);
idct_source_sv = dec->idct_source->get_sampler_view_planes(dec->idct_source);
if (!idct_source_sv)
@@ -187,27 +193,18 @@ error_source_sv:
static void
cleanup_idct_buffer(struct vl_mpeg12_buffer *buf)
{
- struct vl_mpeg12_decoder *dec;
unsigned i;
assert(buf);
- dec = (struct vl_mpeg12_decoder*)buf->base.decoder;
- assert(dec);
-
for (i = 0; i < 3; ++i)
vl_idct_cleanup_buffer(&buf->idct[0]);
}
static bool
-init_mc_buffer(struct vl_mpeg12_buffer *buf)
+init_mc_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buf)
{
- struct vl_mpeg12_decoder *dec;
-
- assert(buf);
-
- dec = (struct vl_mpeg12_decoder*)buf->base.decoder;
- assert(dec);
+ assert(dec && buf);
if(!vl_mc_init_buffer(&dec->mc_y, &buf->mc[0]))
goto error_mc_y;
@@ -241,183 +238,148 @@ cleanup_mc_buffer(struct vl_mpeg12_buffer *buf)
vl_mc_cleanup_buffer(&buf->mc[i]);
}
-static void
-vl_mpeg12_buffer_destroy(struct pipe_video_decode_buffer *buffer)
+static INLINE void
+MacroBlockTypeToPipeWeights(const struct pipe_mpeg12_macroblock *mb, unsigned weights[2])
{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
- struct vl_mpeg12_decoder *dec;
+ assert(mb);
- assert(buf);
-
- dec = (struct vl_mpeg12_decoder*)buf->base.decoder;
- assert(dec);
-
- cleanup_zscan_buffer(buf);
-
- if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
- cleanup_idct_buffer(buf);
-
- cleanup_mc_buffer(buf);
-
- vl_vb_cleanup(&buf->vertex_stream);
-
- FREE(buf);
-}
-
-static void
-vl_mpeg12_buffer_begin_frame(struct pipe_video_decode_buffer *buffer)
-{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
- struct vl_mpeg12_decoder *dec;
-
- struct pipe_sampler_view **sampler_views;
- unsigned i;
-
- assert(buf);
-
- dec = (struct vl_mpeg12_decoder *)buf->base.decoder;
- assert(dec);
-
- vl_vb_map(&buf->vertex_stream, dec->base.context);
-
- sampler_views = buf->zscan_source->get_sampler_view_planes(buf->zscan_source);
-
- assert(sampler_views);
-
- for (i = 0; i < VL_MAX_PLANES; ++i) {
- struct pipe_resource *tex = sampler_views[i]->texture;
- struct pipe_box rect =
- {
- 0, 0, 0,
- tex->width0,
- tex->height0,
- 1
- };
-
- buf->tex_transfer[i] = dec->base.context->get_transfer
- (
- dec->base.context, tex,
- 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
- &rect
- );
-
- buf->texels[i] = dec->base.context->transfer_map(dec->base.context, buf->tex_transfer[i]);
- }
-
- if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
- struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES];
- struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES];
-
- for (i = 0; i < VL_MAX_PLANES; ++i)
- ycbcr_stream[i] = vl_vb_get_ycbcr_stream(&buf->vertex_stream, i);
+ switch (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) {
+ case PIPE_MPEG12_MB_TYPE_MOTION_FORWARD:
+ weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX;
+ weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
+ break;
- for (i = 0; i < VL_MAX_REF_FRAMES; ++i)
- mv_stream[i] = vl_vb_get_mv_stream(&buf->vertex_stream, i);
+ case (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD):
+ weights[0] = PIPE_VIDEO_MV_WEIGHT_HALF;
+ weights[1] = PIPE_VIDEO_MV_WEIGHT_HALF;
+ break;
- vl_mpg12_bs_set_buffers(&buf->bs, ycbcr_stream, buf->texels, mv_stream);
- } else {
+ case PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD:
+ weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN;
+ weights[1] = PIPE_VIDEO_MV_WEIGHT_MAX;
+ break;
- for (i = 0; i < VL_MAX_PLANES; ++i)
- vl_zscan_set_layout(&buf->zscan[i], dec->zscan_linear);
+ default:
+ if (mb->macroblock_type & PIPE_MPEG12_MB_TYPE_PATTERN) {
+ /* patern without a motion vector, just copy the old frame content */
+ weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX;
+ weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
+ } else {
+ weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN;
+ weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
+ }
+ break;
}
}
-static void
-vl_mpeg12_buffer_set_quant_matrix(struct pipe_video_decode_buffer *buffer,
- const uint8_t intra_matrix[64],
- const uint8_t non_intra_matrix[64])
+static INLINE struct vl_motionvector
+MotionVectorToPipe(const struct pipe_mpeg12_macroblock *mb, unsigned vector,
+ unsigned field_select_mask, unsigned weight)
{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
- unsigned i;
+ struct vl_motionvector mv;
+
+ assert(mb);
+
+ if (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) {
+ switch (mb->macroblock_modes.bits.frame_motion_type) {
+ case PIPE_MPEG12_MO_TYPE_FRAME:
+ mv.top.x = mb->PMV[0][vector][0];
+ mv.top.y = mb->PMV[0][vector][1];
+ mv.top.field_select = PIPE_VIDEO_FRAME;
+ mv.top.weight = weight;
+
+ mv.bottom.x = mb->PMV[0][vector][0];
+ mv.bottom.y = mb->PMV[0][vector][1];
+ mv.bottom.weight = weight;
+ mv.bottom.field_select = PIPE_VIDEO_FRAME;
+ break;
+
+ case PIPE_MPEG12_MO_TYPE_FIELD:
+ mv.top.x = mb->PMV[0][vector][0];
+ mv.top.y = mb->PMV[0][vector][1];
+ mv.top.field_select = (mb->motion_vertical_field_select & field_select_mask) ?
+ PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
+ mv.top.weight = weight;
+
+ mv.bottom.x = mb->PMV[1][vector][0];
+ mv.bottom.y = mb->PMV[1][vector][1];
+ mv.bottom.field_select = (mb->motion_vertical_field_select & (field_select_mask << 2)) ?
+ PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
+ mv.bottom.weight = weight;
+ break;
+
+ default: // TODO: Support DUALPRIME and 16x8
+ break;
+ }
+ } else {
+ mv.top.x = mv.top.y = 0;
+ mv.top.field_select = PIPE_VIDEO_FRAME;
+ mv.top.weight = weight;
- for (i = 0; i < VL_MAX_PLANES; ++i) {
- vl_zscan_upload_quant(&buf->zscan[i], intra_matrix, true);
- vl_zscan_upload_quant(&buf->zscan[i], non_intra_matrix, false);
+ mv.bottom.x = mv.bottom.y = 0;
+ mv.bottom.field_select = PIPE_VIDEO_FRAME;
+ mv.bottom.weight = weight;
}
+ return mv;
}
-static struct pipe_ycbcr_block *
-vl_mpeg12_buffer_get_ycbcr_stream(struct pipe_video_decode_buffer *buffer, int component)
-{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
-
- assert(buf);
-
- return vl_vb_get_ycbcr_stream(&buf->vertex_stream, component);
-}
-
-static short *
-vl_mpeg12_buffer_get_ycbcr_buffer(struct pipe_video_decode_buffer *buffer, int component)
-{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
-
- assert(buf);
- assert(component < VL_MAX_PLANES);
-
- return buf->texels[component];
-}
-
-static unsigned
-vl_mpeg12_buffer_get_mv_stream_stride(struct pipe_video_decode_buffer *buffer)
+static INLINE void
+UploadYcbcrBlocks(struct vl_mpeg12_decoder *dec,
+ struct vl_mpeg12_buffer *buf,
+ const struct pipe_mpeg12_macroblock *mb)
{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
+ unsigned intra;
+ unsigned tb, x, y, num_blocks = 0;
- assert(buf);
+ assert(dec && buf);
+ assert(mb);
- return vl_vb_get_mv_stream_stride(&buf->vertex_stream);
-}
-
-static struct pipe_motionvector *
-vl_mpeg12_buffer_get_mv_stream(struct pipe_video_decode_buffer *buffer, int ref_frame)
-{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
-
- assert(buf);
+ if (!mb->coded_block_pattern)
+ return;
- return vl_vb_get_mv_stream(&buf->vertex_stream, ref_frame);
-}
+ intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA ? 1 : 0;
-static void
-vl_mpeg12_buffer_decode_bitstream(struct pipe_video_decode_buffer *buffer,
- unsigned num_bytes, const void *data,
- struct pipe_picture_desc *picture,
- unsigned num_ycbcr_blocks[3])
-{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
- struct pipe_mpeg12_picture_desc *pic = (struct pipe_mpeg12_picture_desc *)picture;
-
- struct vl_mpeg12_decoder *dec;
- unsigned i;
+ for (y = 0; y < 2; ++y) {
+ for (x = 0; x < 2; ++x, ++tb) {
+ if (mb->coded_block_pattern & const_empty_block_mask_420[0][y][x]) {
- assert(buf);
+ struct vl_ycbcr_block *stream = buf->ycbcr_stream[0];
+ stream->x = mb->x * 2 + x;
+ stream->y = mb->y * 2 + y;
+ stream->intra = intra;
+ stream->coding = mb->macroblock_modes.bits.dct_type;
+ stream->block_num = buf->block_num++;
- dec = (struct vl_mpeg12_decoder *)buf->base.decoder;
- assert(dec);
+ buf->num_ycbcr_blocks[0]++;
+ buf->ycbcr_stream[0]++;
- for (i = 0; i < VL_MAX_PLANES; ++i)
- vl_zscan_set_layout(&buf->zscan[i], pic->alternate_scan ? dec->zscan_alternate : dec->zscan_normal);
-
- vl_mpg12_bs_decode(&buf->bs, num_bytes, data, pic, num_ycbcr_blocks);
-}
+ num_blocks++;
+ }
+ }
+ }
-static void
-vl_mpeg12_buffer_end_frame(struct pipe_video_decode_buffer *buffer)
-{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer*)buffer;
- struct vl_mpeg12_decoder *dec;
- unsigned i;
+ /* TODO: Implement 422, 444 */
+ //assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
- assert(buf);
+ for (tb = 1; tb < 3; ++tb) {
+ if (mb->coded_block_pattern & const_empty_block_mask_420[tb][0][0]) {
- dec = (struct vl_mpeg12_decoder *)buf->base.decoder;
- assert(dec);
+ struct vl_ycbcr_block *stream = buf->ycbcr_stream[tb];
+ stream->x = mb->x;
+ stream->y = mb->y;
+ stream->intra = intra;
+ stream->coding = 0;
+ stream->block_num = buf->block_num++;
- vl_vb_unmap(&buf->vertex_stream, dec->base.context);
+ buf->num_ycbcr_blocks[tb]++;
+ buf->ycbcr_stream[tb]++;
- for (i = 0; i < VL_MAX_PLANES; ++i) {
- dec->base.context->transfer_unmap(dec->base.context, buf->tex_transfer[i]);
- dec->base.context->transfer_destroy(dec->base.context, buf->tex_transfer[i]);
+ num_blocks++;
+ }
}
+
+ memcpy(buf->texels, mb->blocks, 64 * sizeof(short) * num_blocks);
+ buf->texels += 64 * num_blocks;
}
static void
@@ -452,7 +414,6 @@ vl_mpeg12_destroy(struct pipe_video_decoder *decoder)
pipe_resource_reference(&dec->quads.buffer, NULL);
pipe_resource_reference(&dec->pos.buffer, NULL);
- pipe_resource_reference(&dec->block_num.buffer, NULL);
pipe_sampler_view_reference(&dec->zscan_linear, NULL);
pipe_sampler_view_reference(&dec->zscan_normal, NULL);
@@ -461,7 +422,7 @@ vl_mpeg12_destroy(struct pipe_video_decoder *decoder)
FREE(dec);
}
-static struct pipe_video_decode_buffer *
+static void *
vl_mpeg12_create_buffer(struct pipe_video_decoder *decoder)
{
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder*)decoder;
@@ -473,38 +434,25 @@ vl_mpeg12_create_buffer(struct pipe_video_decoder *decoder)
if (buffer == NULL)
return NULL;
- buffer->base.decoder = decoder;
- buffer->base.destroy = vl_mpeg12_buffer_destroy;
- buffer->base.begin_frame = vl_mpeg12_buffer_begin_frame;
- buffer->base.set_quant_matrix = vl_mpeg12_buffer_set_quant_matrix;
- buffer->base.get_ycbcr_stream = vl_mpeg12_buffer_get_ycbcr_stream;
- buffer->base.get_ycbcr_buffer = vl_mpeg12_buffer_get_ycbcr_buffer;
- buffer->base.get_mv_stream_stride = vl_mpeg12_buffer_get_mv_stream_stride;
- buffer->base.get_mv_stream = vl_mpeg12_buffer_get_mv_stream;
- buffer->base.decode_bitstream = vl_mpeg12_buffer_decode_bitstream;
- buffer->base.end_frame = vl_mpeg12_buffer_end_frame;
-
if (!vl_vb_init(&buffer->vertex_stream, dec->base.context,
dec->base.width / MACROBLOCK_WIDTH,
dec->base.height / MACROBLOCK_HEIGHT))
goto error_vertex_buffer;
- if (!init_mc_buffer(buffer))
+ if (!init_mc_buffer(dec, buffer))
goto error_mc;
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
- if (!init_idct_buffer(buffer))
+ if (!init_idct_buffer(dec, buffer))
goto error_idct;
- if (!init_zscan_buffer(buffer))
+ if (!init_zscan_buffer(dec, buffer))
goto error_zscan;
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
- vl_mpg12_bs_init(&buffer->bs,
- dec->base.width / MACROBLOCK_WIDTH,
- dec->base.height / MACROBLOCK_HEIGHT);
+ vl_mpg12_bs_init(&buffer->bs, decoder);
- return &buffer->base;
+ return buffer;
error_zscan:
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
@@ -522,76 +470,307 @@ error_vertex_buffer:
}
static void
-vl_mpeg12_decoder_flush_buffer(struct pipe_video_decode_buffer *buffer,
- unsigned num_ycbcr_blocks[3],
- struct pipe_video_buffer *refs[2],
- struct pipe_video_buffer *dst)
+vl_mpeg12_destroy_buffer(struct pipe_video_decoder *decoder, void *buffer)
{
- struct vl_mpeg12_buffer *buf = (struct vl_mpeg12_buffer *)buffer;
- struct vl_mpeg12_decoder *dec;
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder*)decoder;
+ struct vl_mpeg12_buffer *buf = buffer;
+
+ assert(dec && buf);
+
+ cleanup_zscan_buffer(buf);
+
+ if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
+ cleanup_idct_buffer(buf);
+
+ cleanup_mc_buffer(buf);
+
+ vl_vb_cleanup(&buf->vertex_stream);
+
+ FREE(buf);
+}
+
+static void
+vl_mpeg12_set_decode_buffer(struct pipe_video_decoder *decoder, void *buffer)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+
+ assert(dec && buffer);
+
+ dec->current_buffer = buffer;
+}
+
+static void
+vl_mpeg12_set_picture_parameters(struct pipe_video_decoder *decoder,
+ struct pipe_picture_desc *picture)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+ struct pipe_mpeg12_picture_desc *pic = (struct pipe_mpeg12_picture_desc *)picture;
+
+ assert(dec && pic);
+
+ dec->picture_desc = *pic;
+}
+
+static void
+vl_mpeg12_set_quant_matrix(struct pipe_video_decoder *decoder,
+ const struct pipe_quant_matrix *matrix)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+ const struct pipe_mpeg12_quant_matrix *m = (const struct pipe_mpeg12_quant_matrix *)matrix;
+
+ assert(dec);
+ assert(matrix->codec == PIPE_VIDEO_CODEC_MPEG12);
+
+ memcpy(dec->intra_matrix, m->intra_matrix, 64);
+ memcpy(dec->non_intra_matrix, m->non_intra_matrix, 64);
+}
- struct pipe_sampler_view **sv[VL_MAX_REF_FRAMES], **mc_source_sv;
+static void
+vl_mpeg12_set_decode_target(struct pipe_video_decoder *decoder,
+ struct pipe_video_buffer *target)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
struct pipe_surface **surfaces;
+ unsigned i;
+
+ assert(dec);
+
+ surfaces = target->get_surfaces(target);
+ for (i = 0; i < VL_MAX_PLANES; ++i)
+ pipe_surface_reference(&dec->target_surfaces[i], surfaces[i]);
+}
+
+static void
+vl_mpeg12_set_reference_frames(struct pipe_video_decoder *decoder,
+ struct pipe_video_buffer **ref_frames,
+ unsigned num_ref_frames)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+ struct pipe_sampler_view **sv;
+ unsigned i,j;
+
+ assert(dec);
+ assert(num_ref_frames <= VL_MAX_REF_FRAMES);
+
+ for (i = 0; i < num_ref_frames; ++i) {
+ sv = ref_frames[i]->get_sampler_view_planes(ref_frames[i]);
+ for (j = 0; j < VL_MAX_PLANES; ++j)
+ pipe_sampler_view_reference(&dec->ref_frames[i][j], sv[j]);
+ }
+
+ for (; i < VL_MAX_REF_FRAMES; ++i)
+ for (j = 0; j < VL_MAX_PLANES; ++j)
+ pipe_sampler_view_reference(&dec->ref_frames[i][j], NULL);
+}
+
+static void
+vl_mpeg12_begin_frame(struct pipe_video_decoder *decoder)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+ struct vl_mpeg12_buffer *buf;
+
+ struct pipe_resource *tex;
+ struct pipe_box rect = { 0, 0, 0, 1, 1, 1 };
+
+ unsigned i;
+
+ assert(dec);
+
+ buf = dec->current_buffer;
+ assert(buf);
+
+ if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
+ dec->intra_matrix[0] = 1 << (7 - dec->picture_desc.intra_dc_precision);
+
+ for (i = 0; i < VL_MAX_PLANES; ++i) {
+ vl_zscan_upload_quant(&buf->zscan[i], dec->intra_matrix, true);
+ vl_zscan_upload_quant(&buf->zscan[i], dec->non_intra_matrix, false);
+ }
+
+ vl_vb_map(&buf->vertex_stream, dec->base.context);
+
+ tex = buf->zscan_source->texture;
+ rect.width = tex->width0;
+ rect.height = tex->height0;
+
+ buf->tex_transfer = dec->base.context->get_transfer
+ (
+ dec->base.context, tex,
+ 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
+ &rect
+ );
+
+ buf->block_num = 0;
+ buf->texels = dec->base.context->transfer_map(dec->base.context, buf->tex_transfer);
+
+ for (i = 0; i < VL_MAX_PLANES; ++i) {
+ buf->ycbcr_stream[i] = vl_vb_get_ycbcr_stream(&buf->vertex_stream, i);
+ buf->num_ycbcr_blocks[i] = 0;
+ }
+
+ for (i = 0; i < VL_MAX_REF_FRAMES; ++i)
+ buf->mv_stream[i] = vl_vb_get_mv_stream(&buf->vertex_stream, i);
+
+ if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
+ vl_mpg12_bs_set_picture_desc(&buf->bs, &dec->picture_desc);
+
+ } else {
+
+ for (i = 0; i < VL_MAX_PLANES; ++i)
+ vl_zscan_set_layout(&buf->zscan[i], dec->zscan_linear);
+ }
+}
+
+static void
+vl_mpeg12_decode_macroblock(struct pipe_video_decoder *decoder,
+ const struct pipe_macroblock *macroblocks,
+ unsigned num_macroblocks)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+ const struct pipe_mpeg12_macroblock *mb = (const struct pipe_mpeg12_macroblock *)macroblocks;
+ struct vl_mpeg12_buffer *buf;
+
+ unsigned i, j, mv_weights[2];
+
+ assert(dec && dec->current_buffer);
+ assert(macroblocks && macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12);
+
+ buf = dec->current_buffer;
+ assert(buf);
+
+ for (; num_macroblocks > 0; --num_macroblocks) {
+ unsigned mb_addr = mb->y * dec->width_in_macroblocks + mb->x;
+
+ if (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_PATTERN | PIPE_MPEG12_MB_TYPE_INTRA))
+ UploadYcbcrBlocks(dec, buf, mb);
+
+ MacroBlockTypeToPipeWeights(mb, mv_weights);
+
+ for (i = 0; i < 2; ++i) {
+ if (!dec->ref_frames[i][0]) continue;
+
+ buf->mv_stream[i][mb_addr] = MotionVectorToPipe
+ (
+ mb, i,
+ i ? PIPE_MPEG12_FS_FIRST_BACKWARD : PIPE_MPEG12_FS_FIRST_FORWARD,
+ mv_weights[i]
+ );
+ }
+
+ /* see section 7.6.6 of the spec */
+ if (mb->num_skipped_macroblocks > 0) {
+ struct vl_motionvector skipped_mv[2];
+
+ if (dec->ref_frames[0][0] && !dec->ref_frames[1][0]) {
+ skipped_mv[0].top.x = skipped_mv[0].top.y = 0;
+ skipped_mv[0].top.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
+ } else {
+ skipped_mv[0] = buf->mv_stream[0][mb_addr];
+ skipped_mv[1] = buf->mv_stream[1][mb_addr];
+ }
+ skipped_mv[0].top.field_select = PIPE_VIDEO_FRAME;
+ skipped_mv[1].top.field_select = PIPE_VIDEO_FRAME;
+
+ skipped_mv[0].bottom = skipped_mv[0].top;
+ skipped_mv[1].bottom = skipped_mv[1].top;
+
+ ++mb_addr;
+ for (i = 0; i < mb->num_skipped_macroblocks; ++i, ++mb_addr) {
+ for (j = 0; j < 2; ++j) {
+ if (!dec->ref_frames[j][0]) continue;
+ buf->mv_stream[j][mb_addr] = skipped_mv[j];
+
+ }
+ }
+ }
+
+ ++mb;
+ }
+}
+
+static void
+vl_mpeg12_decode_bitstream(struct pipe_video_decoder *decoder,
+ unsigned num_bytes, const void *data)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+ struct vl_mpeg12_buffer *buf;
+
+ unsigned i;
+
+ assert(dec && dec->current_buffer);
+ buf = dec->current_buffer;
+ assert(buf);
+
+ for (i = 0; i < VL_MAX_PLANES; ++i)
+ vl_zscan_set_layout(&buf->zscan[i], dec->picture_desc.alternate_scan ?
+ dec->zscan_alternate : dec->zscan_normal);
+
+ vl_mpg12_bs_decode(&buf->bs, num_bytes, data);
+}
+
+static void
+vl_mpeg12_end_frame(struct pipe_video_decoder *decoder)
+{
+ struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
+ struct pipe_sampler_view **mc_source_sv;
struct pipe_vertex_buffer vb[3];
+ struct vl_mpeg12_buffer *buf;
unsigned i, j, component;
unsigned nr_components;
- assert(buf);
+ assert(dec && dec->current_buffer);
- dec = (struct vl_mpeg12_decoder *)buf->base.decoder;
- assert(dec);
+ buf = dec->current_buffer;
+
+ vl_vb_unmap(&buf->vertex_stream, dec->base.context);
- for (i = 0; i < 2; ++i)
- sv[i] = refs[i] ? refs[i]->get_sampler_view_planes(refs[i]) : NULL;
+ dec->base.context->transfer_unmap(dec->base.context, buf->tex_transfer);
+ dec->base.context->transfer_destroy(dec->base.context, buf->tex_transfer);
vb[0] = dec->quads;
vb[1] = dec->pos;
- surfaces = dst->get_surfaces(dst);
-
dec->base.context->bind_vertex_elements_state(dec->base.context, dec->ves_mv);
for (i = 0; i < VL_MAX_PLANES; ++i) {
- if (!surfaces[i]) continue;
+ if (!dec->target_surfaces[i]) continue;
- vl_mc_set_surface(&buf->mc[i], surfaces[i]);
+ vl_mc_set_surface(&buf->mc[i], dec->target_surfaces[i]);
for (j = 0; j < VL_MAX_REF_FRAMES; ++j) {
- if (!sv[j]) continue;
+ if (!dec->ref_frames[j][i]) continue;
vb[2] = vl_vb_get_mv(&buf->vertex_stream, j);;
dec->base.context->set_vertex_buffers(dec->base.context, 3, vb);
- vl_mc_render_ref(&buf->mc[i], sv[j][i]);
+ vl_mc_render_ref(&buf->mc[i], dec->ref_frames[j][i]);
}
}
- vb[2] = dec->block_num;
-
dec->base.context->bind_vertex_elements_state(dec->base.context, dec->ves_ycbcr);
for (i = 0; i < VL_MAX_PLANES; ++i) {
- if (!num_ycbcr_blocks[i]) continue;
+ if (!buf->num_ycbcr_blocks[i]) continue;
vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, i);
- dec->base.context->set_vertex_buffers(dec->base.context, 3, vb);
+ dec->base.context->set_vertex_buffers(dec->base.context, 2, vb);
- vl_zscan_render(&buf->zscan[i] , num_ycbcr_blocks[i]);
+ vl_zscan_render(&buf->zscan[i] , buf->num_ycbcr_blocks[i]);
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
- vl_idct_flush(&buf->idct[i], num_ycbcr_blocks[i]);
+ vl_idct_flush(&buf->idct[i], buf->num_ycbcr_blocks[i]);
}
mc_source_sv = dec->mc_source->get_sampler_view_planes(dec->mc_source);
for (i = 0, component = 0; i < VL_MAX_PLANES; ++i) {
- if (!surfaces[i]) continue;
+ if (!dec->target_surfaces[i]) continue;
- nr_components = util_format_get_nr_components(surfaces[i]->texture->format);
+ nr_components = util_format_get_nr_components(dec->target_surfaces[i]->texture->format);
for (j = 0; j < nr_components; ++j, ++component) {
- if (!num_ycbcr_blocks[i]) continue;
+ if (!buf->num_ycbcr_blocks[i]) continue;
vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, component);
- dec->base.context->set_vertex_buffers(dec->base.context, 3, vb);
+ dec->base.context->set_vertex_buffers(dec->base.context, 2, vb);
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
vl_idct_prepare_stage2(&buf->idct[component]);
@@ -599,11 +778,19 @@ vl_mpeg12_decoder_flush_buffer(struct pipe_video_decode_buffer *buffer,
dec->base.context->set_fragment_sampler_views(dec->base.context, 1, &mc_source_sv[component]);
dec->base.context->bind_fragment_sampler_states(dec->base.context, 1, &dec->sampler_ycbcr);
}
- vl_mc_render_ycbcr(&buf->mc[i], j, num_ycbcr_blocks[component]);
+ vl_mc_render_ycbcr(&buf->mc[i], j, buf->num_ycbcr_blocks[component]);
}
}
}
+static void
+vl_mpeg12_flush(struct pipe_video_decoder *decoder)
+{
+ assert(decoder);
+
+ //Noop, for shaders it is much faster to flush everything in end_frame
+}
+
static bool
init_pipe_state(struct vl_mpeg12_decoder *dec)
{
@@ -870,21 +1057,21 @@ vl_create_mpeg12_decoder(struct pipe_context *context,
dec->base.destroy = vl_mpeg12_destroy;
dec->base.create_buffer = vl_mpeg12_create_buffer;
- dec->base.flush_buffer = vl_mpeg12_decoder_flush_buffer;
+ dec->base.destroy_buffer = vl_mpeg12_destroy_buffer;
+ dec->base.set_decode_buffer = vl_mpeg12_set_decode_buffer;
+ dec->base.set_picture_parameters = vl_mpeg12_set_picture_parameters;
+ dec->base.set_quant_matrix = vl_mpeg12_set_quant_matrix;
+ dec->base.set_decode_target = vl_mpeg12_set_decode_target;
+ dec->base.set_reference_frames = vl_mpeg12_set_reference_frames;
+ dec->base.begin_frame = vl_mpeg12_begin_frame;
+ dec->base.decode_macroblock = vl_mpeg12_decode_macroblock;
+ dec->base.decode_bitstream = vl_mpeg12_decode_bitstream;
+ dec->base.end_frame = vl_mpeg12_end_frame;
+ dec->base.flush = vl_mpeg12_flush;
dec->blocks_per_line = MAX2(util_next_power_of_two(dec->base.width) / block_size_pixels, 4);
dec->num_blocks = (dec->base.width * dec->base.height) / block_size_pixels;
-
- dec->quads = vl_vb_upload_quads(dec->base.context);
- dec->pos = vl_vb_upload_pos(
- dec->base.context,
- dec->base.width / MACROBLOCK_WIDTH,
- dec->base.height / MACROBLOCK_HEIGHT
- );
- dec->block_num = vl_vb_upload_block_num(dec->base.context, dec->num_blocks);
-
- dec->ves_ycbcr = vl_vb_get_ves_ycbcr(dec->base.context);
- dec->ves_mv = vl_vb_get_ves_mv(dec->base.context);
+ dec->width_in_macroblocks = align(dec->base.width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
/* TODO: Implement 422, 444 */
assert(dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
@@ -892,14 +1079,27 @@ vl_create_mpeg12_decoder(struct pipe_context *context,
if (dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
dec->chroma_width = dec->base.width / 2;
dec->chroma_height = dec->base.height / 2;
+ dec->num_blocks = dec->num_blocks * 2;
} else if (dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
dec->chroma_width = dec->base.width;
dec->chroma_height = dec->base.height / 2;
+ dec->num_blocks = dec->num_blocks * 2 + dec->num_blocks;
} else {
dec->chroma_width = dec->base.width;
dec->chroma_height = dec->base.height;
+ dec->num_blocks = dec->num_blocks * 3;
}
+ dec->quads = vl_vb_upload_quads(dec->base.context);
+ dec->pos = vl_vb_upload_pos(
+ dec->base.context,
+ dec->base.width / MACROBLOCK_WIDTH,
+ dec->base.height / MACROBLOCK_HEIGHT
+ );
+
+ dec->ves_ycbcr = vl_vb_get_ves_ycbcr(dec->base.context);
+ dec->ves_mv = vl_vb_get_ves_mv(dec->base.context);
+
switch (entrypoint) {
case PIPE_VIDEO_ENTRYPOINT_BITSTREAM:
format_config = find_format_config(dec, bitstream_format_config, num_bitstream_format_configs);
@@ -946,6 +1146,9 @@ vl_create_mpeg12_decoder(struct pipe_context *context,
if (!init_pipe_state(dec))
goto error_pipe_state;
+ memset(dec->intra_matrix, 0x10, 64);
+ memset(dec->non_intra_matrix, 0x10, 64);
+
return &dec->base;
error_pipe_state:
diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h
index 01265e368a3..4a8d65335f6 100644
--- a/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h
+++ b/src/gallium/auxiliary/vl/vl_mpeg12_decoder.h
@@ -49,12 +49,12 @@ struct vl_mpeg12_decoder
unsigned blocks_per_line;
unsigned num_blocks;
+ unsigned width_in_macroblocks;
enum pipe_format zscan_source_format;
struct pipe_vertex_buffer quads;
struct pipe_vertex_buffer pos;
- struct pipe_vertex_buffer block_num;
void *ves_ycbcr;
void *ves_mv;
@@ -73,23 +73,34 @@ struct vl_mpeg12_decoder
struct vl_mc mc_y, mc_c;
void *dsa;
+
+ struct vl_mpeg12_buffer *current_buffer;
+ struct pipe_mpeg12_picture_desc picture_desc;
+ uint8_t intra_matrix[64];
+ uint8_t non_intra_matrix[64];
+ struct pipe_sampler_view *ref_frames[VL_MAX_REF_FRAMES][VL_MAX_PLANES];
+ struct pipe_surface *target_surfaces[VL_MAX_PLANES];
};
struct vl_mpeg12_buffer
{
- struct pipe_video_decode_buffer base;
-
struct vl_vertex_buffer vertex_stream;
- struct pipe_video_buffer *zscan_source;
+ unsigned block_num;
+ unsigned num_ycbcr_blocks[3];
+
+ struct pipe_sampler_view *zscan_source;
struct vl_mpg12_bs bs;
struct vl_zscan_buffer zscan[VL_MAX_PLANES];
struct vl_idct_buffer idct[VL_MAX_PLANES];
struct vl_mc_buffer mc[VL_MAX_PLANES];
- struct pipe_transfer *tex_transfer[VL_MAX_PLANES];
- short *texels[VL_MAX_PLANES];
+ struct pipe_transfer *tex_transfer;
+ short *texels;
+
+ struct vl_ycbcr_block *ycbcr_stream[VL_MAX_PLANES];
+ struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES];
};
/**
diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.c b/src/gallium/auxiliary/vl/vl_vertex_buffers.c
index c0f1449bf80..281db8018eb 100644
--- a/src/gallium/auxiliary/vl/vl_vertex_buffers.c
+++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.c
@@ -125,49 +125,6 @@ vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height)
return pos;
}
-struct pipe_vertex_buffer
-vl_vb_upload_block_num(struct pipe_context *pipe, unsigned num_blocks)
-{
- struct pipe_vertex_buffer buf;
- struct pipe_transfer *buf_transfer;
- struct vertex2s *v;
- unsigned i;
-
- assert(pipe);
-
- /* create buffer */
- buf.stride = sizeof(struct vertex2s);
- buf.buffer_offset = 0;
- buf.buffer = pipe_buffer_create
- (
- pipe->screen,
- PIPE_BIND_VERTEX_BUFFER,
- PIPE_USAGE_STATIC,
- sizeof(struct vertex2s) * num_blocks
- );
-
- if(!buf.buffer)
- return buf;
-
- /* and fill it */
- v = pipe_buffer_map
- (
- pipe,
- buf.buffer,
- PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
- &buf_transfer
- );
-
- for ( i = 0; i < num_blocks; ++i, ++v) {
- v->x = i;
- v->y = i;
- }
-
- pipe_buffer_unmap(pipe, buf_transfer);
-
- return buf;
-}
-
static struct pipe_vertex_element
vl_vb_get_quad_vertex_element(void)
{
@@ -211,12 +168,10 @@ vl_vb_get_ves_ycbcr(struct pipe_context *pipe)
/* Position element */
vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED;
- vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1);
-
/* block num element */
- vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R16G16_SSCALED;
+ vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R32_FLOAT;
- vl_vb_element_helper(&vertex_elems[VS_I_BLOCK_NUM], 1, 2);
+ vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 2, 1);
return pipe->create_vertex_elements_state(pipe, 3, vertex_elems);
}
@@ -266,7 +221,7 @@ vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe,
pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM,
- sizeof(struct pipe_ycbcr_block) * size * 4
+ sizeof(struct vl_ycbcr_block) * size * 4
);
if (!buffer->ycbcr[i].resource)
goto error_ycbcr;
@@ -278,7 +233,7 @@ vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe,
pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM,
- sizeof(struct pipe_motionvector) * size
+ sizeof(struct vl_motionvector) * size
);
if (!buffer->mv[i].resource)
goto error_mv;
@@ -310,7 +265,7 @@ vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component)
assert(buffer);
- buf.stride = sizeof(struct pipe_ycbcr_block);
+ buf.stride = sizeof(struct vl_ycbcr_block);
buf.buffer_offset = 0;
buf.buffer = buffer->ycbcr[component].resource;
@@ -324,7 +279,7 @@ vl_vb_get_mv(struct vl_vertex_buffer *buffer, int motionvector)
assert(buffer);
- buf.stride = sizeof(struct pipe_motionvector);
+ buf.stride = sizeof(struct vl_motionvector);
buf.buffer_offset = 0;
buf.buffer = buffer->mv[motionvector].resource;
@@ -360,7 +315,7 @@ vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
}
-struct pipe_ycbcr_block *
+struct vl_ycbcr_block *
vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component)
{
assert(buffer);
@@ -377,7 +332,7 @@ vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer)
return buffer->width;
}
-struct pipe_motionvector *
+struct vl_motionvector *
vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame)
{
assert(buffer);
diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.h b/src/gallium/auxiliary/vl/vl_vertex_buffers.h
index 74845a42b69..874ecce9041 100644
--- a/src/gallium/auxiliary/vl/vl_vertex_buffers.h
+++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.h
@@ -52,20 +52,56 @@ enum VS_INPUT
NUM_VS_INPUTS = 4
};
+enum vl_mv_weight
+{
+ PIPE_VIDEO_MV_WEIGHT_MIN = 0,
+ PIPE_VIDEO_MV_WEIGHT_HALF = 128,
+ PIPE_VIDEO_MV_WEIGHT_MAX = 256
+};
+
+enum vl_field_select
+{
+ PIPE_VIDEO_FRAME = 0,
+ PIPE_VIDEO_TOP_FIELD = 1,
+ PIPE_VIDEO_BOTTOM_FIELD = 3,
+
+ /* TODO
+ PIPE_VIDEO_DUALPRIME
+ PIPE_VIDEO_16x8
+ */
+};
+
+struct vl_motionvector
+{
+ struct {
+ int16_t x, y;
+ int16_t field_select; /**< enum pipe_video_field_select */
+ int16_t weight; /**< enum pipe_video_mv_weight */
+ } top, bottom;
+};
+
+struct vl_ycbcr_block
+{
+ uint8_t x, y;
+ uint8_t intra;
+ uint8_t coding;
+ float block_num;
+};
+
struct vl_vertex_buffer
{
unsigned width, height;
struct {
- struct pipe_resource *resource;
- struct pipe_transfer *transfer;
- struct pipe_ycbcr_block *vertex_stream;
+ struct pipe_resource *resource;
+ struct pipe_transfer *transfer;
+ struct vl_ycbcr_block *vertex_stream;
} ycbcr[VL_MAX_PLANES];
struct {
- struct pipe_resource *resource;
- struct pipe_transfer *transfer;
- struct pipe_motionvector *vertex_stream;
+ struct pipe_resource *resource;
+ struct pipe_transfer *transfer;
+ struct vl_motionvector *vertex_stream;
} mv[VL_MAX_REF_FRAMES];
};
@@ -73,8 +109,6 @@ struct pipe_vertex_buffer vl_vb_upload_quads(struct pipe_context *pipe);
struct pipe_vertex_buffer vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height);
-struct pipe_vertex_buffer vl_vb_upload_block_num(struct pipe_context *pipe, unsigned num_blocks);
-
void *vl_vb_get_ves_ycbcr(struct pipe_context *pipe);
void *vl_vb_get_ves_mv(struct pipe_context *pipe);
@@ -89,13 +123,13 @@ void vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe);
struct pipe_vertex_buffer vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component);
-struct pipe_ycbcr_block *vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component);
+struct vl_ycbcr_block *vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component);
struct pipe_vertex_buffer vl_vb_get_mv(struct vl_vertex_buffer *buffer, int ref_frame);
unsigned vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer);
-struct pipe_motionvector *vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame);
+struct vl_motionvector *vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame);
void vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe);
diff --git a/src/gallium/auxiliary/vl/vl_vlc.h b/src/gallium/auxiliary/vl/vl_vlc.h
index e81b1e9afd2..4db1334d6a4 100644
--- a/src/gallium/auxiliary/vl/vl_vlc.h
+++ b/src/gallium/auxiliary/vl/vl_vlc.h
@@ -25,116 +25,148 @@
*
**************************************************************************/
-/**
- * This file is based uppon slice_xvmc.c and vlc.h from the xine project,
- * which in turn is based on mpeg2dec. The following is the original copyright:
- *
- * Copyright (C) 2000-2002 Michel Lespinasse <[email protected]>
- * Copyright (C) 1999-2000 Aaron Holtzman <[email protected]>
- *
- * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
- * See http://libmpeg2.sourceforge.net/ for updates.
- *
- * mpeg2dec 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 2 of the License, or
- * (at your option) any later version.
- *
- * mpeg2dec 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
#ifndef vl_vlc_h
#define vl_vlc_h
-#include "pipe/p_compiler.h"
+#include <assert.h>
+
+#include <pipe/p_compiler.h>
+
+#include <util/u_math.h>
+#include "util/u_pointer.h"
struct vl_vlc
{
- uint32_t buf; /* current 32 bit working set of buffer */
- int bits; /* used bits in working set */
- const uint8_t *ptr; /* buffer with stream data */
- const uint8_t *max; /* ptr+len of buffer */
+ uint64_t buffer;
+ unsigned valid_bits;
+ uint32_t *data;
+ uint32_t *end;
+};
+
+struct vl_vlc_entry
+{
+ int8_t length;
+ int8_t value;
+};
+
+struct vl_vlc_compressed
+{
+ uint16_t bitcode;
+ struct vl_vlc_entry entry;
};
static INLINE void
-vl_vlc_restart(struct vl_vlc *vlc)
+vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size)
{
- vlc->buf = (vlc->ptr[0] << 24) | (vlc->ptr[1] << 16) | (vlc->ptr[2] << 8) | vlc->ptr[3];
- vlc->bits = -16;
- vlc->ptr += 4;
+ unsigned i, bits = util_logbase2(dst_size);
+
+ for (i=0;i<dst_size;++i) {
+ dst[i].length = 0;
+ dst[i].value = 0;
+ }
+
+ for(; src_size > 0; --src_size, ++src) {
+ for(i=0; i<(1 << (bits - src->entry.length)); ++i)
+ dst[src->bitcode >> (16 - bits) | i] = src->entry;
+ }
+}
+
+static INLINE void
+vl_vlc_fillbits(struct vl_vlc *vlc)
+{
+ if (vlc->valid_bits < 32) {
+ uint32_t value = *vlc->data;
+
+ //assert(vlc->data <= vlc->end);
+
+#ifndef PIPE_ARCH_BIG_ENDIAN
+ value = util_bswap32(value);
+#endif
+
+ vlc->buffer |= (uint64_t)value << (32 - vlc->valid_bits);
+ ++vlc->data;
+ vlc->valid_bits += 32;
+ }
}
static INLINE void
vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, unsigned len)
{
- vlc->ptr = data;
- vlc->max = data + len;
- vl_vlc_restart(vlc);
+ assert(vlc);
+ assert(data && len);
+
+ vlc->buffer = 0;
+ vlc->valid_bits = 0;
+
+ /* align the data pointer */
+ while (pointer_to_uintptr(data) & 3) {
+ vlc->buffer |= (uint64_t)*data << (56 - vlc->valid_bits);
+ ++data;
+ --len;
+ vlc->valid_bits += 8;
+ }
+ vlc->data = (uint32_t*)data;
+ vlc->end = (uint32_t*)(data + len);
+
+ vl_vlc_fillbits(vlc);
+ vl_vlc_fillbits(vlc);
+}
+
+static INLINE unsigned
+vl_vlc_bytes_left(struct vl_vlc *vlc)
+{
+ return ((uint8_t*)vlc->end)-((uint8_t*)vlc->data);
}
-static INLINE bool
-vl_vlc_getbyte(struct vl_vlc *vlc)
+static INLINE unsigned
+vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits)
{
- vlc->buf <<= 8;
- vlc->buf |= vlc->ptr[0];
- vlc->ptr++;
- return vlc->ptr < vlc->max;
+ //assert(vlc->valid_bits >= num_bits);
+
+ return vlc->buffer >> (64 - num_bits);
}
-#define vl_vlc_getword(vlc, shift) \
-do { \
- (vlc)->buf |= (((vlc)->ptr[0] << 8) | (vlc)->ptr[1]) << (shift); \
- (vlc)->ptr += 2; \
-} while (0)
-
-/* make sure that there are at least 16 valid bits in bit_buf */
-#define vl_vlc_needbits(vlc) \
-do { \
- if ((vlc)->bits >= 0) { \
- vl_vlc_getword(vlc, (vlc)->bits); \
- (vlc)->bits -= 16; \
- } \
-} while (0)
-
-/* make sure that the full 32 bit of the buffer are valid */
static INLINE void
-vl_vlc_need32bits(struct vl_vlc *vlc)
+vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits)
{
- vl_vlc_needbits(vlc);
- if (vlc->bits > -8) {
- unsigned n = -vlc->bits;
- vlc->buf <<= n;
- vlc->buf |= *vlc->ptr << 8;
- vlc->bits = -8;
- vlc->ptr++;
- }
- if (vlc->bits > -16) {
- unsigned n = -vlc->bits - 8;
- vlc->buf <<= n;
- vlc->buf |= *vlc->ptr;
- vlc->bits = -16;
- vlc->ptr++;
- }
+ //assert(vlc->valid_bits > num_bits);
+
+ vlc->buffer <<= num_bits;
+ vlc->valid_bits -= num_bits;
}
-/* remove num valid bits from bit_buf */
-#define vl_vlc_dumpbits(vlc, num) \
-do { \
- (vlc)->buf <<= (num); \
- (vlc)->bits += (num); \
-} while (0)
+static INLINE unsigned
+vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits)
+{
+ unsigned value;
+
+ //assert(vlc->valid_bits >= num_bits);
+
+ value = vlc->buffer >> (64 - num_bits);
+ vl_vlc_eatbits(vlc, num_bits);
+
+ return value;
+}
+
+static INLINE signed
+vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits)
+{
+ signed value;
+
+ //assert(vlc->valid_bits >= num_bits);
+
+ value = ((int64_t)vlc->buffer) >> (64 - num_bits);
+ vl_vlc_eatbits(vlc, num_bits);
-/* take num bits from the high part of bit_buf and zero extend them */
-#define vl_vlc_ubits(vlc, num) (((uint32_t)((vlc)->buf)) >> (32 - (num)))
+ return value;
+}
-/* take num bits from the high part of bit_buf and sign extend them */
-#define vl_vlc_sbits(vlc, num) (((int32_t)((vlc)->buf)) >> (32 - (num)))
+static INLINE int8_t
+vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits)
+{
+ tbl += vl_vlc_peekbits(vlc, num_bits);
+ vl_vlc_eatbits(vlc, tbl->length);
+ return tbl->value;
+}
#endif /* vl_vlc_h */